我接受了以下面试问题:
class A
{
public:
void fun()
{
std::cout << "fun" << std::endl;
}
};
A* a = NULL;
a->fun();
执行此代码时会发生什么?为什么?
答案 0 :(得分:56)
这是未定义的行为,所以任何事情都可能发生。
可能的结果是它只打印"fun"
,因为该方法不会访问被调用对象的任何成员变量(不需要访问对象所在的内存,所以不一定会发生访问冲突。)
答案 1 :(得分:22)
按照标准,这是未定义的行为,因此是一件非常糟糕的事情。实际上,大多数编程平台(跨越X86和其他几种架构)都可以正常运行。
为什么呢?考虑如何在C ++中实现类函数。这不是虚函数,因此可以是对已知地址的静态调用。 在x86程序集中,我们可以将其视为
mov A, 0
mov ecx, A
call a__fun
因为a__fun不需要实例数据,即使它接收到null指针,也不会发生任何事情。
仍然是糟糕的代码,任何编译器都会尖叫,但它可以运行。
答案 2 :(得分:14)
在大多数现代计算机上,最可能的行为是它会运行并打印“有趣”,因为:
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()
函数中没有使用/调用任何成员变量和虚函数,因此工作正常。