这个让我想到:
class X;
void foo(X* p)
{
delete p;
}
如果我们甚至不知道delete p
是否有可见的析构函数,我们怎么可能X
? g ++ 4.5.1给出了三个警告:
warning: possible problem detected in invocation of delete operator: warning: 'p' has incomplete type warning: forward declaration of 'struct X'
然后它说:
注意:析构函数和类特定运算符都不会删除 将被调用,即使它们是在定义类时声明的。
哇......像g ++一样诊断这种情况需要编译器吗?还是未定义的行为?
答案 0 :(得分:21)
来自标准[expr.delete]:
如果要删除的对象有 不完整的类型 删除和完整的类有一个 非平凡的析构函数或者 解除分配函数,行为是 未定义。
所以,如果有非常重要的事情要做,那就是UB,如果没有,那就没关系。 UB不需要警告。
答案 1 :(得分:6)
这是未定义的行为。
但是,您可以让编译器检查不完整的类型,例如boost:
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
}
将sizeof
应用于不完整类型会触发错误,我想如果它通过某些编译器传递,那么负数大小的数组会触发错误。
答案 2 :(得分:3)
这是未定义的行为,是实现pImpl模式时常见的问题。据我所知,根本不需要编译器需要发出的警告。警告是选修课;他们在那里是因为编译器编写者认为它们会很有用。