28

这让我想到:

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'

然后它说:

注意:析构函数和特定于类的操作符 delete 都不会被调用,即使它们是在定义类时声明的。

哇...是否需要编译器来像 g++ 那样诊断这种情况?或者它是未定义的行为?

4

3 回答 3

22

从标准[expr.delete]:

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

所以,如果有重要的事情要做,那就是 UB,如果没有也没关系。UB 不需要警告。

于 2010-12-01T14:13:42.577 回答
7

这是未定义的行为。

但是,您可以让编译器检查不完整的类型,例如 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不完整的类型应该会触发错误,我想如果通过某些编译器可以通过,那么负大小的数组会触发错误。

于 2010-12-01T15:25:15.853 回答
4

这是未定义的行为,也是实现 pImpl 模式时的常见问题。据我所知,根本没有编译器需要发出警告之类的东西。警告是可选的;它们在那里是因为编译器作者认为它们会很有用。

于 2010-12-01T14:12:02.197 回答