C ++:未使用嵌入式模板调用析构函数

C++: Destructor not called with embedded template

简而言之:删除模板化指针不会调用析构函数。

include 解决了这个问题。为什么?

我只是 运行 陷入了无法解释的境地。我试着在这里分解更复杂的情况。

文件R.cpp

class R {
      Owner<Problem> m_o;
      void cleanUp() { m_o.clear(); }
     }

文件Owner.cpp

struct DeleteFunctor {
  template< class TPtr > void operator()(TPtr* ptr) {  delete ptr; }
};

template< class T >
class Owner { 
std::vector<T*> m_objects; 
// here add and other stuff
void clear() {
  std::for_each( m_objects.begin(), m_objects.end(), DeleteFunctor() );
  m_objects.clear();
}

我现在有一个实用程序 class,可以在堆上创建新的 Problem-objects 并将它们直接插入到 m_o 中。我知道导出对内部类型的引用是不好的风格,但这不是重点。

如果我调用 cleanUp(),我可以追踪到 Functor 中的 delete ptr 调用,其中 ptr 具有正确的 Problem-type。但是 Problem-destructor 没有被调用!!

但是,在文件 R.cpp 中包含问题 header 可以解决问题。编译器没有抱怨。那是编译器错误吗?

系统: g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

来自标准(草案 n3242)§5.3.5/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.

如果在这种情况下不包含定义 TProblem 的 header,那么您将删除不完整类型的 object。如果该类型不满足该条款中的要求,则删除具有未定义的行为。

Is that a compiler bug?

不,编译器不需要警告未定义的行为。

您可能需要 Owner 项中的 T 项才能完成。如果 T 不完整,像 static_assert(sizeof(T) > 0) 这样的东西应该编译失败。

如果您不能依赖当前标准,您可以改用 boost::checked_deleter 作为删除函子。它在 pre c++11 中进行完整性检查。如果您出于某种原因不想包含提升 header,那么只需重新实现它即可。这是检查完整性的代码。

// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;

请注意,您部分有效 re-implementing std::vector<std::unique_ptr<T>> 如果您可以使用 c++11,我建议改用它。