为什么不使用空自动PTR不会终止程序?
Why doesn't using a NULL autoPtr terminate the program?
#include<iostream>
using namespace std;
template<class T>
class autoPtr
{
public:
autoPtr(T* ptr)
{
cout<<"autoPtr ctr"<<endl;
loc=ptr;
}
autoPtr()
{
loc=NULL;
cout<<"autoPtr dflt ctr"<<endl;
}
~autoPtr()
{
cout<<"autoPtr dtr"<<endl;
delete loc;
}
//assignment operator
autoPtr& operator=(autoPtr& rRef)
{
cout<<"autoPtr assignment operator"<<endl;
loc=rRef.loc;
rRef.loc=NULL;
return *this;
}
T* operator->()
{
cout<<"address -"<<loc<<endl;
return loc;
}
private:
T* loc;
};
class base
{
public:
base()
{
cout<<"base ctr"<<endl;
}
~base()
{
cout<<"base dtr"<<endl;
}
void printHello(int i)
{
cout<<"HELLO : "<<i<<endl;
}
};
int main()
{
autoPtr<base> ptr(new base());
autoPtr<base> ptr1;
ptr1=ptr;
ptr1->printHello(1);
ptr->printHello(2); //should make the program terminate, but not so ?
}
问题是:
ptr->printHello(2);
应该使程序终止,但它没有。为什么不呢?
因为你很幸运。您的程序会导致未定义的行为。
ptr1 = ptr
此代码为第一个auto_ptr
对象ptr
分配NULL地址,为第二个对象ptr1
分配一些非NULL地址。源对象在分配期间丢失引用(=(。
执行语句时:
ptr->printHello(2);
ptr
是NULL
指针,取消引用NULL指针是未定义的行为。
但是由于在函数printHello()
中,您不访问任何类成员变量,所以它可以正常工作。在类中添加一个成员变量,然后尝试在printHello()
函数中访问该变量,您将看到它(很可能(崩溃
需要注意的是,未定义的行为意味着任何事情都可能发生,并且行为不能根据C++标准中的语言规范进行定义。在这种情况下,它有效的事实并不能保证它总是有效的,而且它仍然是一种未定义的行为。
ptr->printHello(2);//should make the program terminate.but not so...y ??
不一定。它实际上是未定义的行为。如果幸运的话,你的程序会崩溃。
未定义的行为不能保证任何定义的行为。所以你不知道在执行上面的行时会发生什么。
你犯了一个BIG错误,你越早纠正它,你的C++生活就会越好。这个错误将崩溃与错误混为一谈。
取消引用NULL指针是"未定义的行为"。这并不意味着你会得到一个运行时错误。这并不意味着你的程序会崩溃。这并不意味着会发生任何有用的事情。这并不意味着你所希望的一切都会发生。
这意味着任何事情都可能发生。
什么都不包括。
事实上,"一无所有"是一种非常常见的情况,也是一种非常危险的情况。即使存在未定义的行为错误,程序也会保持正常工作。
当然,直到大的演示日,他们会撞到你的脸上,让你的节目变得悲惨和美好,只为嘲笑它。
你会开始指责操作系统、编译器、硬件、"运气不好"等等。
未定义的行为,加上C++的复杂性,有时还有不合逻辑的规则和选择,使语言变得非常危险,不可能通过实验来学习。认真思考你写的每一行C++。语言中无法言喻的假设是,你永远不会犯那种错误。
C++中没有"运行时错误天使"。只是"未定义的行为守护程序"。
PS:您的实现不处理复制构造函数。
所有指出使用NULL指针是未定义行为而不是保证崩溃的人当然都是100%正确的。
然而,在这种情况下,有一些非常具体的东西使这里的结果不太可能是崩溃:也就是说,您调用的printhello()
方法是而不是虚拟函数。这意味着进行调用的代码实际上不需要知道对象地址:它是(或者至少可以是,我相信通常是(链接的&调用的方式与简单的全局函数几乎相同。
对象地址当然是计算出来的,并作为隐藏的this
参数传递给函数(因为它不是静态函数(,但这并不意味着不能调用该函数。我认为如果你在printhello()
中打印出this
,你会看到它打印出0,但这并不意味着你的程序会崩溃。
当然,正如其他人所指出的,只要您引用任何成员变量或调用任何虚拟方法,就很可能崩溃(因为在这种情况下,您使用this
作为指向对象的指针,而对象已不再是对象(一个重要的演示也可能会增加崩溃的可能性!(。
- 堆栈粉碎终止程序
- 为什么我的显示功能会终止程序?
- 调用 raise(signal) 会终止 c++ 程序
- 使用终止程序的指针在数组中输入字符串
- C++ Argv[1] 终止程序,返回值 9009
- protobuf "oneof" sub-protobuf 对象指针终止程序
- 有没有办法避免在发生堆栈粉碎时终止程序
- c++ 终止程序的内存泄漏何时重要?
- C :CTRL D终止程序(Ubuntu)
- 用信号25终止程序,超过文件尺寸限制;为什么
- 是否有一种方法可以在输入负数时平均不包括负数,这是您终止程序的方式
- 正确关闭应用程序:终止程序的替代方案
- 提升线程终止程序
- Shell脚本终止程序,但导致无法写入输出文件
- 访问引用变量会终止程序
- 需要使用"enter"密钥终止程序
- C++按Enter键终止程序
- std::向量使用const_iterator终止程序
- Unicode导致关闭消息框终止程序
- 为什么不使用空自动PTR不会终止程序?