18

可能重复:
通过 NULL 类指针调用类方法

#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

4 回答 4

36

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

于 2012-07-04T00:07:29.937 回答
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) 压入堆栈并调用该方法,因为该方法的地址与实际对象实例无关。

于 2012-07-04T00:15:10.897 回答
3

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

于 2012-07-04T00:08:08.257 回答
1

好吧,首先,它是无效的,因为它会调用未定义的行为。您真的在问为什么编译器允许它,答案是因为那是在实际应用程序中根本不会出现的愚蠢代码,那么为什么要麻烦呢?当指针在运行时以静态代码分析无法预料的方式变为无效时,真正的问题就出现了。

编译器不是用来牵你的手的,它是用来根据标准编译你的代码的。如果它提供有用的警告,那就太好了,但那里没有语法或语义上的非法内容,您只是在编写导致未定义行为的代码。

于 2012-07-04T00:09:42.033 回答