2016-09-18 17 views
2

(例如,在使用线程构建模块的内存池)如果容器和分配器都是同一个内存池的一部分,我还需要调用std :: container的析构函数吗?

可以说我有以下设置:

using MemoryPool = tbb::memory_pool<std::allocator<char>>; 
using CustomAllocator = tbb::memory_pool_allocator<Result*>; 
using CustomVector = std::vector<Result*, CustomAllocator>; 

MemoryPool shortTermPool; 
void* allocatedMemory = shortTermPool.malloc(sizeof(CustomVector); 
CustomVector* results = static_cast<CustomVector*>(allocatedMemory); 
new(results) CustomVector(CustomAllocator(shortTemPool)); 

后来我打电话

shortTermPool.recycle(); 

这行代码回收所有的内存内存池,允许我重用它。现在,既然矢量和它的分配器都在使用内存池,我是否仍然需要在回收内存池之前调用

results->~vector(); 

?析构函数是否做了其他任何事情,或者将整个池回收足够吗?

+0

是的。您可以安全地假定,在对象的存储被破坏之前,所有对象都有必须执行的析构器操作。你使用placement new来构造一个对象。所有构建的对象都必须销毁。调用对象的析构函数是实际销毁它的必需部分。 –

+0

假设我不在上面的例子中调用析构函数。内存中为矢量结果留下了什么。内存池中的内存中是否有东西被分配? (假设任何Result *对象也是使用同一个内存池构造的))。 – user1432882

+0

除非调用析构函数,否则会导致未定义的行为。如果你想验证这对你的特定C++实现没有任何不良影响,那么继续吧。但是答案仅限于你的C++实现。调用析构函数不是一项艰巨的任务。这很容易。而且,这将避免意想不到的惊喜,未来,基本容器应该被更复杂的东西所取代。 –

回答

1

从C++标准:

3.8对象寿命

的程序可以通过重新使用该对象占据存储或通过显式 调用结束任何对象的生命周期具有非平凡析构函数的类类型对象的析构函数。 对于具有非平凡析构函数的类类型的对象,在对象占用的存储被重用或释放之前,不需要显式调用析构函数;然而,如果 没有对析构函数的显式调用,或者没有使用删除表达式 (5.3.5)来释放存储空间,那么析构函数不应该被隐式调用,并且任何依赖于副作用的程序都会被调用 由析构函数生成的行为不确定。

这取决于是否std::vector析构函数是非平凡的,并有副作用程序依赖。因为它是一个库类,建议调用析构函数以保证安全。否则,您现在必须检查std::vector的实现,以确保您的代码与所有标准库兼容。
如果矢量类是你自己的,那么你将控制析构函数的实现,如果它不重要,或者没有程序依赖的副作用,你可以省略它的调用,如上所述。
(但我个人也会在这种情况下称之为)。

+3

供参考:std :: vector的析构函数不是微不足道的,正如标准所要求的那样。 –

相关问题