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.
如果在这种情况下不包含定义 T
或 Problem
的 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,我建议改用它。
简而言之:删除模板化指针不会调用析构函数。
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.
如果在这种情况下不包含定义 T
或 Problem
的 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,我建议改用它。