为什么在C ++中通过空指针调用方法“工作”?

时间:2012-07-04 00:05:00

标签: c++

  

可能重复:
  Calling class method through NULL class pointer

#include <iostream>
using namespace std;
class test
{
    int i;
public:
    test():i(0){ cout << "ctor called" << endl;}
    void show()
    {
        cout<<"show fun called"<<endl;
    }
};

int main(int argc , char *argv[])
{
    test *ptr = NULL;
    ptr->show();
    return 0;
}
显然,不会打电话给ctor。这是标准吗?或者只是一些编译器优化,因为这个指针没有在show()成员函数中使用?

4 个答案:

答案 0 :(得分:24)

调用该方法不需要指针。指针的类型是已知的,因此该方法的代码是已知的。该方法不使用this,因此它运行代码就好了。它是未定义的行为,但更有效的是不检查指针是否为NULL,因此它运行。

答案 1 :(得分:10)

如果你看一下程序集(对于至少一个编译器),你可以看到它运行的原因(即使它是未定义的行为,正如许多人所指出的那样)。对于这两行:

test *ptr = NULL;
ptr->show();

生成此程序集(在我刚试过的一个编译器中):

00000004: C7 45 FC 00 00 00  mov         dword ptr [ebp-4],0
          00
0000000B: 8B 4D FC           mov         ecx,dword ptr [ebp-4]
0000000E: E8 00 00 00 00     call        ?show@test@@QAEXXZ

它推送堆栈上的NULL(0)并调用该方法,因为该方法的地址独立于实际的对象实例。

答案 2 :(得分:1)

它无效,行为未定义,实际结果取决于您的编译器。

答案 3 :(得分:0)

嗯,首先,它无效,因为它会调用未定义的行为。你真的在问为什么编译器允许它,答案是因为这是一个根本不会在真实应用程序中出现的骨头代码,为什么要这么麻烦?当指针在运行时无效时,真正的问题就出现了静态代码分析无法预料的方式。

编译器无法抓住您的手,它可以根据标准编译您的代码。如果它提供有用的警告那么好,但在那里没有任何语法或语义上的非法,你只是编写导致未定义行为的代码。