在下面的代码片段中,虽然指针未初始化,但仍然可以成功调用
temp *ptr;
ptr->func2();
是由于C ++语言属性,还是VC ++ 6编译器是犯规的?
class temp {
public:
temp():a(9){}
int& func1()
{
return a;
}
bool func2(int arg)
{
if(arg%2==0)
return true;
return false;
}
int a;
};
int main(int argc, char **argv)
{
temp *ptr;
int a;
cin>>a;
if(ptr->func2(a))
{
cout<<"Good poniner"<<endl;
}
ptr->func1(); // Does not crash here
int crashere=ptr->func1();// But does crash here
return 0;
}
答案 0 :(得分:14)
C ++编译器不会阻止您使用未初始化的指针,虽然结果未定义,但现实世界中的编译器生成的代码忽略指针未初始化的事实是正常的。
这就是为什么C ++相对于其他语言来说既快速又相对危险的原因之一。
您对func2
的调用成功的原因是它没有触及其this
指针。从不使用指针值,因此不会导致问题。在func1
中你做使用this
指针(访问成员变量),这就是崩溃的原因。
答案 1 :(得分:7)
根据标准,这完全依赖于编译器和未定义的行为。你不应该依赖这个。
调用func2()
成功,因为在编译时已知调用的确切方法(调用不是虚拟的),并且方法本身不会取消引用此指针。所以这个无效。
ptr->func1(); // This works
因为指示编译器返回对类成员的引用。为此,它只是将成员的偏移量添加到 this 指针的无效值,并产生另一个无效指针(引用,它几乎相同)。
int crashere=ptr->func1();// Crashes here
因为现在指示编译器通过该无效引用检索值,这会导致程序崩溃。
答案 2 :(得分:3)
C ++有Undefined Behavior的概念。使用未初始化的指针是此类未定义行为的常见示例。出于性能原因,C ++标准对可能的结果放置无限制。也就是说,格式化硬盘是完全可以接受的。
答案 3 :(得分:0)
我怀疑ptr->func2()
被优化掉了,因为它总是返回true。但正如Richie所说,在这种情况下,指针的使用就像你一样;不要触及任何实例数据(a),因此没有任何东西可以崩溃。
答案 4 :(得分:0)
它不起作用。幸运的是,您的应用程序不会在您希望崩溃的地方崩溃。它不是一个功能,而是编译器的副作用,它允许函数调用似乎起作用。