我是否需要shared_ptr的删除器来释放分配器分配的内存?

时间:2013-11-21 11:48:03

标签: c++ memory stl

我想使用shared_ptr来管理动态分配的数组。在我了解STL分配器的存在之前,我总是使用new []来分配内存并为shared_ptr写一个删除器以释放它。然后代码看起来像:

struct ArrayDeleter
{
   void operator()(int* p) { delete [] p; }
};
...
...
std::shared_ptr<int> array(new int[100], ArrayDeleter());
...

如果没有ArrayDeleter释放内存,valgrind等工具将报告不平衡的new []和delete []的内存错误。我理解这个问题是由shared_ptr调用delete而不是delete[]来释放内存引起的。

但是,我想知道分配器分配的内存是否相同。我的代码看起来像是:

std::allocator<int> alloc;
std::shared_ptr<int> array(alloc.allocate(10));
...

因此代码中没有提供特定的删除器。然后我用valgrind检查了程序,但这一次,它没有抱怨任何东西。所以我可以安全地假设std :: allocator被实现为使用new来分配内存,所以std :: shared_ptr使用的默认delete运算符可以用它吗?

我实现自己的分配器怎么样?我是对的,不使用new运算符的自定义分配器会破坏上面的代码,即我还需要删除器吗?

1 个答案:

答案 0 :(得分:1)

  

我可以安全地假设std :: allocator被实现为使用new   分配内存,以便使用默认的delete运算符   std :: shared_ptr可以用吗?

不,你不能。默认std::allocator<T>定义为使用全局::operator new分配内存,但我不认为每次调用allocate都会导致只调用一次::operator new,或者allocate()返回的值等于new返回的值。

释放内存的正确方法是在分配器上调用deallocate(),它将使用全局::operator delete

因此,您的代码无法正确释放数据。它恰好在您的实现中工作std::allocator没有对分配做任何特殊操作,并且在delete上调用int*的行为与调用全局运算符{{1}相同}。对于其他类型或其他实现,它可能会失败。

此外,delete不初始化对象,因此调用allocate()会将析构函数调用为从未构造过的内存。如果类型不是微不足道的话,这会有未定义的行为(delete是微不足道的。)

出于同样的原因,您的代码也不一定适用于自定义分配器。