在不完整类型的空指针上调用delete是否合法?

时间:2017-11-17 15:07:17

标签: c++ language-lawyer delete-operator incomplete-type nullptr

如果是这样,为什么下面的代码会给我警告

  

注意:即使在定义类时声明它们,也不会调用析构函数或类特定的运算符delete

struct C;

int main()
{
    C *c = nullptr;

    delete c;

    return 0;
}

理解为什么可能在一般情况下是未定义的行为,如果C具有非平凡/虚拟析构函数,但不是标准保证/定义delete上的nullptr始终是noop,无论情况如何?

重申:我具体询问指向不完整类型的指针为nullptr的情况!

1 个答案:

答案 0 :(得分:16)

标准说([expr.delete] / 5):

  

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

因此,如果T具有非平凡的析构函数或具有operator delete重载,则会获得UB。关于UB基于指针的没有任何说法(即:它是否为空指针)。

关于什么"被删除的对象"意思?

有人可以认为#34;对象被删除"表示此子句仅适用于对实际对象的delete调用。因此,如果传递空指针,则不适用。

首先,关于delete行为的其余标准讨论明确地指出它的行为不适用于空指针。 [expr.delete] / 6& 7都以&#34开头;如果delete-expression的操作数值不是空指针值"。第5段明确不包含这些词。因此,我们必须假设它确实适用于空指针。

第二,"对象被删除的含义是什么?"如果它被传递一个空指针?毕竟,没有"对象"那里。

那么,如果"对象被删除"请考虑解释此文本意味着什么。具体谈到该指针末尾的对象。那么,如果您正在使用非平凡的析构函数删除不完整的类数组,会发生什么?

通过该逻辑,该子句不适用,无论指针是否为空。为什么?因为"对象被删除"是数组类型,而不是类类型。因此,本条款不适用。这意味着编译器必须能够在不完整类的数组上调用delete[]

它需要编译器能够跟踪尚不存在的代码。

所以&#34;对象被删除&#34; 意图引用std::remove_pointer_t<std::decay_t<decltype(expr)>>,或标准要求无法实现的行为。标准措辞可能会被清理一下,取而代之的是#34;如果要删除的对象在删除时具有不完整的类类型&#34;使用&#34;如果T是指向UU数组的指针,并且U在删除时具有不完整的类类型,...& #34;

相关问题