向上转换空指针是否会导致未定义的行为

Does upcasting a null pointer lead to undefined behavior

我想知道以下代码是否会导致未定义的行为:

#include <cstddef>
#include <cstdio>

struct IA { 
  virtual ~IA() {}
  int a = 0;
};
struct IB {
  virtual ~IB() {}
  int b = 0;
};
struct C: IA, IB {};

int main() {
  C* pc = nullptr;
  IB* pib = pc;
  std::printf("%p %p", (void*)pc, (void*)pib);
}

Stroustrup 在 his 1989 multiple inheritance paper [PDF] 的第 4.5 节中讨论了这种情况:

The solution is to elaborate the conversion (casting) operation to test for the pointer-value 0 [...]

The added complexity and run-time overhead are a test and an increment.

实现明确检查空值并确保强制转换的结果仍然是空值。这在 C++98 中是正确的,并且在 C++11 和 nullptr.

中没有改变

这在多个基数 classes 的情况下尤其重要,其中从派生 class 到其中一个基数 classes 的转换可能需要更改实际值指针。

在您的示例中,C 在内存中的布局将首先包含 IA 的字节,然后是 IB 的字节。转换为 IA 很简单,因为指向 C 开头的指针也将指向 CIA 部分的开头。另一方面,转换为 IB 需要将 C 指针移动 IA 的大小。在 nullptr 情况下执行此移位将导致转换后的非空指针,因此对空值进行特殊处理。

作为,标准中的相关部分是[conv.ptr] §4.10:

A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class [...] of D. [...] The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.

向上转换空指针明确定义为您提供另一个空指针:

4.10p3:

A prvalue of type "pointer to cv D", where D is a class type, can be converted to a prvalue of type "pointer to cv B", where B is a base class of D. ... The null pointer value is converted to the null pointer value of the destination type.