如果是这样,为什么下面的代码会给我警告
注意:即使在定义类时声明它们,也不会调用析构函数或类特定的运算符delete
struct C;
int main()
{
C *c = nullptr;
delete c;
return 0;
}
我理解为什么可能在一般情况下是未定义的行为,如果C
具有非平凡/虚拟析构函数,但不是标准保证/定义delete
上的nullptr
始终是noop
,无论情况如何?
重申:我具体询问指向不完整类型的指针为nullptr
的情况!
答案 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
是指向U
或U
数组的指针,并且U
在删除时具有不完整的类类型,...& #34;