C ++ 11标准是否允许在不调用其析构函数的情况下结束容器(例如std :: map)的生存期,如果此类容器不需要调用其包含的元素的析构函数并且内存不需要被释放(使用Allocator :: deallocate)。
C ++ 11标准规定以下内容:
程序可以通过重用对象占用的存储空间或通过使用非平凡的析构函数显式调用类类型的对象的析构函数来结束任何对象的生命周期。对于具有非平凡析构函数的类类型的对象,在重用或释放该对象占用的存储空间之前,不需要程序显式调用析构函数。但是,如果没有对析构函数的显式调用,或者未使用delete-expression(5.3.5)释放存储,则不应隐式调用析构函数,并且任何依赖于析构函数产生的副作用的程序具有未定义的行为。
这是明确而直接的。例如,有一些对象在其生命周期内分配内存,并在销毁时释放内存。如果程序依赖释放内存,则不调用对象的析构函数会导致未定义的行为。另一方面,如果对象从某个内存池中获取内存,则无需调用析构函数,因为程序不依赖于其副作用,并且行为已明确定义。
但是STL容器(例如std :: map,std :: list等)呢?标准规定符合规范的实施必须遵循AS-IF规则。只要可观察到的行为是相同的,则实现方式可能会有所不同。
我想说的是,例如,如表96中所述(容器要求),容器的析构函数应调用其元素的析构函数并释放所有内存。但是,如果它内部也使用了一些互斥锁,该怎么办?标准不禁止在容器内部使用容器(我错了吗?)。不调用互斥量的析构函数可能会导致不确定的行为。
我想知道,如果标准允许使用std :: map并在不调用destructor的情况下终止其生存期。例如,std :: map使用自定义分配器。该分配器使用一些内存池,并且释放内存不需要重新分配功能。由于容器中的所有内存都是使用此分配器获得的,因此使用此类容器的程序不依赖于析构函数的副作用。
代码:
class MemoryPool
{
public:
...
// Pre-allocates memory.
// Returns true on success.
bool initialize(uint32_t size)
{
...
}
// Returns properly aligned block of memory from pre-allocated area.
template <class T> T* allocate(size_t n = 1)
{
...
}
...
};
template <class T> class CustomAllocator
{
public:
CustomAllocator(MemoryPool& memoryPool): memoryPool_(&memoryPool) {}
...
/* this allocator obtains memory from memory pool */
T* allocate(size_t n)
{
return memoryPool_->allocate<T>(n);
}
// This function may be a no-op, it depends on the implementation of
// memory pool. It doesn't really matter in context of this question.
// Anyway, all memory is already allocated in memory pool, so whether there
// is a need to mark unused chunks or not depends on actual application.
void deallocate(T*, size_t) {}
...
private:
MemoryPool* memoryPool_;
...
};
MemoryPool memoryPool;
memoryPool.initialize();
// I intentionally use only fundamental types in this map
// since not invoking the destructors of such objects
// will not lead to undefined behavior
typedef std::map
<
uint32_t, uint32_t,
std::less<uint32_t>,
CustomAllocator<uint32_t>
> SomeMap;
SomeMap* someMap = memoryPool.allocate<SomeMap>();
new(someMap) SomeMap(CustomAllocator<uint32_t>{memoryPool});
// no destructor of SomeMap is called
// memory is deallocated in destructor of memory pool
我在这里提出了这个问题:https : //groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/R_KPazXbE0k
根据17.5.2.3 / 1:
第18至30条和附件D没有规定类别的表示,有意省略了类别成员的规定(9.2)。实现可以根据需要定义静态或非静态类成员,或同时定义这两个类,以实现第18至30条和附件D中指定的成员函数的语义。
换句话说,实现可能具有一些私有成员,这些私有成员使用内存以外的资源。因此,不能保证没有其他副作用(至少在当前的C ++ 11标准中)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句