使用make_shared创建shared_ptr是否有任何缺点

Tob*_*olm 51 c++ boost shared-ptr

使用make_shared<T>()而不是使用是否有任何缺点shared_ptr<T>(new T).

提升文档状态

用户一再请求工厂函数创建给定类型的对象并向其返回shared_ptr.除了方便和风格之外,这样的函数也是异常安全且相当快的,因为它可以对对象及其相应的控制块使用单个分配,从而消除了shared_ptr的构造开销的很大一部分.这消除了关于shared_ptr的主要效率投诉之一.

sbk*_*sbk 39

除了@deft_code提供的点之外,还有一个更弱的点:

  • 如果你weak_ptrshared_ptr给定对象的所有s都死之后使用了s ,那么这个对象的内存将与控制块一起存在于内存中,直到最后一个weak_ptr死掉.换句话说,对象被销毁但在最后一个weak_ptr被销毁之前不会被释放.

  • @Mike:肯定不会 - 通常,如果对象没有shared_ptrs,只有weak_ptrs,则会立即删除该对象.我不知道控制块是否仍然存在,我会接受你的话.使用make_shared,控制块和对象共同使用单个分配,所以如果其中一个的内存保持不变,那么(虽然我猜对象被破坏,只是内存没有被释放?). (13认同)
  • 呃,是的 抱歉.当我写这篇文章的时候,我肯定已经有了另一个脑子. (3认同)

def*_*ode 26

我至少知道两个.

  • 你必须控制分配.真的不是一个大的,但是一些旧的api喜欢返回你必须删除的指针.
  • 没有自定义删除器.我不知道为什么不支持,但事实并非如此.这意味着你的共享指针必须使用一个vanilla删除器.

相当弱点.所以尽量使用make_shared.

  • 没有自定义删除器,因为只有`make_shared`本身知道如何删除对象. (6认同)
  • 自定义删除器用于做一些有趣的技巧,不仅限于删除,这就是deft_code提到它的原因. (4认同)
  • @MikeSeymour:从`shared_ptr`的角度来看,是的,它需要有一个由`make_shared()`提供的自定义删除器,但是提供`make_shared()`的调用者是可能的,也许是有用的.能够运行从`make_shared()自己的自定义删除器内部运行的自定义"子删除器". (2认同)
  • 我所说的是它看起来像这样:`template <class T,class Allocator,class Deleter,class ... Args> shared_ptr <T> make_shared2(Allocator a,Deleter d,Args ... args) ;"是的,它可以提供,但它不是很漂亮. (2认同)

Vik*_*ehr 14

来自http://www.codesynthesis.com/~boris/blog/2010/05/24/smart-pointers-in-boost-tr1-cxx-x0/

make_shared()实现的另一个缺点是对象代码大小的增加.由于这种优化的实现方式,额外的虚拟表以及一组虚拟功能将被实例化,你有make_shared使用()每个对象类型.


Rok*_*iša 8

此外,make_shared与工厂模式不兼容.这是因为对make_shared工厂函数内的调用会调用库代码,而库代码又调用new它无法访问的库代码,因为它无法调用类的私有构造函数(构造函数应该是私有的,如果你正确遵循工厂模式).


Joh*_*erg 7

使用make shared,您无法指定如何完成保持对象的分配释放.

如果需要,请std::allocate_shared<T>改用:

std::vector<std::shared_ptr<std::string>> avec; 
std::allocator<std::string> aAllocator;
avec.push_back(std::allocate_shared<std::string>(aAllocator,"hi there!"));
Run Code Online (Sandbox Code Playgroud)

请注意,向量不需要被告知分配器!

要制作自定义分配器,请查看/sf/answers/37963761/