C++:未使用嵌入模板调用析构函数
C++: Destructor not called with embedded template
简而言之:删除模板化指针不会调用析构函数。
include解决了问题。为什么
我只是遇到了一个我无法解释的情况。我试图打破这里更复杂的局面。
文件R.cpp
class R {
Owner<Problem> m_o;
void cleanUp() { m_o.clear(); }
}
文件所有者.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();
}
我现在有一个实用程序类,它在堆上创建新的Problem对象,并将它们直接插入m_o中。我知道将引用导出到内部类型是不好的风格,但这不是重点。
如果我调用cleanUp(),我可以追踪到Functor中的调用delete ptr,其中ptr具有正确的Problem类型。但是问题析构函数没有被调用!!
但是,在R.cpp文件中包含Problem标头可以修复该问题。滑稽演员没有抱怨。这是编译器错误吗?
系统:g++(Ubuntu 4.8.2-19ubuntu1)4.8.2
根据标准(草案n3242)§5.3.5/5:
如果被删除的对象在删除时具有不完整的类类型,并且完整的类具有非平凡的析构函数或释放函数,则行为是未定义的。
如果在这种情况下没有包含定义T
或Problem
的标头,那么您正在删除一个不完整类型的对象。如果该类型不满足该子句中的要求,则删除具有未定义的行为。
这是编译器错误吗?
不需要,编译器不需要对未定义的行为发出警告。
您可能需要Owner
中的T
是完整的。如果T
不完整,像static_assert(sizeof(T) > 0)
这样的东西应该无法编译。
如果不能依赖当前的标准,则可以使用boost::checked_deleter
作为删除函数。它在预c++11中进行完整性检查。如果你出于某种原因不想包含boost头,那么就重新实现它。这是检查完整性的代码。
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete x;
请注意,您实际上部分地重新实现了std::vector<std::unique_ptr<T>>
。如果您可以使用c++11,我建议您改用它。
- 什么时候调用析构函数
- C++-明确何时以及如何调用析构函数
- C++ 防止在映射中放置()时调用析构函数
- 调用析构函数以释放动态分配的内存
- C++:使用方法调用析构函数的顺序是什么?
- 向量推回调用析构函数时调用析构函数
- 如何在调用析构函数时优雅地停止/销毁带有阻塞调用C++线程?
- C++,我应该调用析构函数吗?
- 如何获取有关在 Clang LibTooling 中调用析构函数的信息?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 为什么这里不调用析构函数
- 在调用 std::bind 的产品后意外调用析构函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 如何在C++中调用析构函数
- 为什么为未删除的对象调用析构函数?
- 调用析构函数时出错
- C++ 在不释放内存的情况下调用析构函数
- 为什么在运算符删除中不调用析构函数?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 postOrderDelete 上调用析构函数时引发的异常