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

时间:2010-03-28 15:46:27

标签: c++

我接受了以下面试问题:

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

A* a = NULL;
a->fun();

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


另见:

6 个答案:

答案 0 :(得分:56)

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

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

答案 1 :(得分:22)

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

为什么呢?考虑如何在C ++中实现类函数。这不是虚函数,因此可以是对已知地址的静态调用。 在x86程序集中,我们可以将其视为

mov A, 0
mov ecx, A
call a__fun

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

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

答案 2 :(得分:14)

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

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

答案 3 :(得分:9)

我们无法知道。所有都可以发生,因为程序暴露了未定义的行为。请参阅Does invoking a member function on a null instance cause undefined behavior?

答案 4 :(得分:6)

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

答案 5 :(得分:0)

三点可能会有所帮助:

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

2)非虚拟功能在编译时解决。

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

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