当我在NULL对象指针上调用成员函数时会发生什么?

Raj*_*pal 44 c++

我接受了以下面试问题:

class A
{
public:
    void fun()
    {
        std::cout << "fun" << std::endl;
    }
};

A* a = NULL;
a->fun();
Run Code Online (Sandbox Code Playgroud)

执行此代码时会发生什么,为什么?


也可以看看:

sth*_*sth 57

这是未定义的行为,所以任何事情都可能发生.

一个可能的结果是它只是打印,"fun"因为该方法不访问它被调用的对象的任何成员变量(不需要访问对象所在的内存,因此不一定会发生访问冲突).

  • @Kamal如果该函数不是虚函数,则它将静态链接.不需要桌子.不需要对象指针. (9认同)
  • @Kamal编译器可以使用静态信息(它知道指针是A类型)来查找函数.编译器可以执行此操作的事实意味着它必须,并且不会阻止它成为未定义的行为. (4认同)
  • @Kamal:编译器知道对象的类型和应该在编译时调用的方法的地址,并且可以插入该地址"硬编码".没有必要在运行时查找任何内容.(这并不意味着编译器*有*这样做,但它可以.) (2认同)

Dan*_*erg 22

按照标准,这是不确定的行为,因此是一件非常糟糕的事情.实际上,大多数编程平台(跨X86和其他几种架构)都可以正常运行.

为什么?考虑如何在C++中实现类函数.这不是虚函数,因此可以是对已知地址的静态调用.在x86汇编中,我们可以看到这一点

mov A, 0
mov ecx, A
call a__fun
Run Code Online (Sandbox Code Playgroud)

因为a__fun不需要实例数据,即使它接收到null这个指针,也不会发生任何事情.

仍然糟糕的代码和任何编译器都会尖叫,但它可以运行.

  • 是的,这是未定义的行为.是的,这个*可能*在给定的架构上按预期运行.然而,始终牢记以下智慧是明智的:"未定义行为的最坏可能结果是它能够做你期望的事情." (2认同)

Ken*_*oom 15

在大多数现代计算机上,最可能的行为是它将运行并打印"有趣",因为:

  • 在调用函数之前,C++不检查指针是否为NULL
  • fun() 不是虚拟的,所以不需要引用vtable来调用 fun()
  • fun()永远不会访问任何成员变量,A因此不需要取消引用空this指针.

  • 3.`A*a = NULL; a-> fun();`在函数体之外是非法的. (3认同)
  • 但我认为我们仍然可以弯曲我们的想法并有点理解他的意思 (2认同)

Joh*_*itb 9

我们不知道是什么.一切都可能发生,因为程序暴露了未定义的行为.请参阅在null实例上调用成员函数是否会导致未定义的行为?.


Use*_*321 6

我已经尝试了多次,所有时间输出都变得"有趣",这是因为函数fun独立于实例a.虽然调用a->fun(); a指向0所以这是未定义的行为,但在大多数编译器中应该没有崩溃.


小智 5

三点可能会有所帮助:

1) 所有函数都存储在代码或文本部分。

2) 非虚函数在编译时解析。

3)在调用类的成员函数时,我们将当前对象作为this指向该函数的指针传递。

说到你的问题,这里的fun()函数已经在内存中(代码部分/文本部分)。由于函数fun()是非 virtual ,它将在编译时解析(即,对于这一行,它将跳转到代码段处的指令 X ,指针为thisas NULL)。由于函数中没有使用/调用成员变量和虚函数fun(),因此它工作正常。