10

在下面的代码中,怎么可能允许使用私有析构函数删除对象?我已将实际程序简化为以下示例,但它仍然可以编译和工作。

class SomeClass;

int main(int argc, char *argv[])
{
  SomeClass* boo = 0; // in real program it will be valid pointer
  delete boo; // how it can work?

  return -1;
}

class SomeClass
{
private:
  ~SomeClass() {}; // ! private destructor !
};
4

3 回答 3

15

您正在尝试删除不完整类类型的对象。C++ 标准说在这种情况下你会得到未定义的行为(5.3.5/5):

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

要检测这种情况,您可以使用boost::checked_delete

template<typename T> 
inline void checked_delete( T* p )
{
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete p;
}
于 2009-10-23T07:01:15.820 回答
8

此代码会导致未定义的行为 (UB)。delete对于具有非平凡析构函数的不完整类型的对象,它是 C++ 中的 UB 。并且在您的代码中,类型SomeClass在 处不完整delete,并且它具有重要的析构函数。编译器通常会对此发出警告,因为在正式的 C++ 中,这不是违反约束的。

所以,严格来说,你的代码不能“工作”。它只是编译并在运行时执行一些未定义的操作。

编译器不需要捕捉这个错误。这样做的原因是,如果你的对象有一个微不足道的析构函数,这可能会很好。编译器无法知道这种类型最终将具有什么样的析构函数,因此无法确定这是否是错误。

于 2009-10-23T07:00:20.733 回答
4

因为SomeClass调用时类型没有完全声明operator delete

删除这样的指针是未定义的行为,但实际上大多数编译器只会释放内存(如果指针非 NULL)而不调用析构函数。

例如,g++ 会给你一个关于这个问题的警告:

foo.cpp: In function 'int main(int, char**)':
foo.cpp:6: warning: possible problem detected in invocation of delete operator:
foo.cpp:5: warning: 'boo' has incomplete type
foo.cpp:1: warning: forward declaration of 'struct SomeClass'
foo.cpp:6: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
于 2009-10-23T07:01:13.883 回答