在不完整类型的空指针上调用 delete 是否合法?
Is it legal to call delete on a null pointer of an incomplete type?
如果是这样,为什么下面的代码会给我警告
note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
?
struct C;
int main()
{
C *c = nullptr;
delete c;
return 0;
}
我理解为什么如果C
有non-trivial/virtual析构函数,在一般情况下可能是未定义的行为, 但标准 guarantee/define nullptr
上的 delete
是否总是 noop
无论情况如何?
重申一下:我特别询问指向不完整类型的指针是 nullptr
!
的情况
标准说 ([expr.delete]/5):
If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.
因此,如果 T
具有非平凡的析构函数或具有 operator delete
重载,您将获得 UB。关于 UB 基于指针的 value(即:它是否为空指针)没有任何说明。
"object being deleted" 是什么意思?
可以认为 "object being deleted" 意味着该子句仅适用于对实际对象的 delete
调用。因此,如果您传递一个空指针,它不适用。
首先,关于 delete
行为的其余标准讨论明确指出其行为不适用于空指针。 [expr.delete]/6&7 均以 "If the value of the operand of the delete-expression is not a null pointer value" 开头。第 5 段 明确地 不包含这些词。因此,我们必须假设它确实适用于空指针。
其次,如果给"object being deleted"传递一个空指针,它的含义是什么?毕竟那里没有"object"
好吧,如果 "object being deleted" 专门讨论该指针末尾的对象,请考虑解释此文本的含义。好吧,如果您要删除具有非平凡析构函数的不完整 classes 数组,会发生什么情况?
根据该逻辑,此子句不适用,无论指针是否为空。为什么?因为 "object being deleted" 是 array 类型,而不是 class 类型。因此,该条款不能适用。这意味着编译器必须能够在不完整的 classes.
数组上调用 delete[]
但这不可能实施;它将要求编译器能够追踪尚不存在的代码。
因此,要么 "object being deleted" 打算 引用 std::remove_pointer_t<std::decay_t<decltype(expr)>>
,要么标准要求的行为无法实现。标准措辞可能会稍微清理一下,将 "If the object being deleted has incomplete class type at the point of deletion" 替换为 "If T
is a pointer to U
or an array of U
, and U
has incomplete class type at the point of deletion, ..."
如果是这样,为什么下面的代码会给我警告
note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
?
struct C;
int main()
{
C *c = nullptr;
delete c;
return 0;
}
我理解为什么如果C
有non-trivial/virtual析构函数,在一般情况下可能是未定义的行为, 但标准 guarantee/define nullptr
上的 delete
是否总是 noop
无论情况如何?
重申一下:我特别询问指向不完整类型的指针是 nullptr
!
标准说 ([expr.delete]/5):
If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.
因此,如果 T
具有非平凡的析构函数或具有 operator delete
重载,您将获得 UB。关于 UB 基于指针的 value(即:它是否为空指针)没有任何说明。
"object being deleted" 是什么意思?
可以认为 "object being deleted" 意味着该子句仅适用于对实际对象的 delete
调用。因此,如果您传递一个空指针,它不适用。
首先,关于 delete
行为的其余标准讨论明确指出其行为不适用于空指针。 [expr.delete]/6&7 均以 "If the value of the operand of the delete-expression is not a null pointer value" 开头。第 5 段 明确地 不包含这些词。因此,我们必须假设它确实适用于空指针。
其次,如果给"object being deleted"传递一个空指针,它的含义是什么?毕竟那里没有"object"
好吧,如果 "object being deleted" 专门讨论该指针末尾的对象,请考虑解释此文本的含义。好吧,如果您要删除具有非平凡析构函数的不完整 classes 数组,会发生什么情况?
根据该逻辑,此子句不适用,无论指针是否为空。为什么?因为 "object being deleted" 是 array 类型,而不是 class 类型。因此,该条款不能适用。这意味着编译器必须能够在不完整的 classes.
数组上调用delete[]
但这不可能实施;它将要求编译器能够追踪尚不存在的代码。
因此,要么 "object being deleted" 打算 引用 std::remove_pointer_t<std::decay_t<decltype(expr)>>
,要么标准要求的行为无法实现。标准措辞可能会稍微清理一下,将 "If the object being deleted has incomplete class type at the point of deletion" 替换为 "If T
is a pointer to U
or an array of U
, and U
has incomplete class type at the point of deletion, ..."