为什么删除不完整的类型定义为"undefined behaviour"?

Why is the deletion of an incomplete type defined as "undefined behaviour"?

本文关键字:undefined behaviour 定义 类型 删除 为什么      更新时间:2023-10-16

为什么删除不完整类型定义为"未定义行为"

来自C++规范;§5.3.5/5;

如果要删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为未定义

给定代码示例(我理解为什么它是一个错误);

class ABC;
int main()
{
    ABC* p = nullptr;
    delete p;
}

当gcc、clang和msvc都警告它是一个不完整的类型时,为什么它被定义为是未定义的行为?为什么不只是在这一点上出错,即为什么它不是可诊断的错误

因为,正如您的引号所说,只有当它具有非平凡的析构函数或释放函数时,它才是未定义的行为。如果它是不完整的,编译器不知道情况是否如此,也不知道程序是否定义良好。

表达式delete p;做两件事:

  1. 销毁包含*p的完整对象
  2. 取消分配用于存储所述对象的内存

当您只知道对象的地址,而不需要任何进一步的信息时,项目2可能是。内存分配器只关心地址。但是,确定完整对象的地址可能很困难;您基本上需要保证您实际上提供了一个完整对象的地址。

但还有更多。在释放对象的存储之前,必须运行析构函数(项1)。如果析构函数没有效果,那么不运行析构函数是可以接受的,因为这与运行它们时的行为相同。但是,如果运行析构函数确实有效果,那么省略第1项会导致未定义的行为,并且您需要知道完整的类型才能知道如何运行destrutors。同样,您还需要知道完整的类型,以便确定项2的派生对象最多的地址。