为什么删除不完整的类型定义为“未定义的行为”?

时间:2014-10-28 12:40:04

标签: c++ language-lawyer

为什么删除不完整类型定义为“未定义的行为”

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

  

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

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

class ABC;

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

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

2 个答案:

答案 0 :(得分:5)

因为,正如你的引语所说,如果它有一个非平凡的析构函数或释放函数,它只是未定义的行为。如果它不完整,编译器不知道是否是这种情况,因此不知道程序是否定义明确。

答案 1 :(得分:3)

表达式delete p;做了两件事:

  1. 销毁包含*p
  2. 的完整对象
  3. 释放用于存储所述对象的内存。
  4. 当你所知道的只是对象的地址时,项目2 可能,而没有任何进一步的信息。内存分配器只关心地址。但确定完整对象的地址可能很困难;你基本上需要承诺你实际上提供了一个完整对象的地址。

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