C++ 使用make_shared创建共享的_ptr有什么缺点吗

C++ 使用make_shared创建共享的_ptr有什么缺点吗,c++,boost,shared-ptr,C++,Boost,Shared Ptr,使用make_shared()而不是使用shared_ptr(新T)有什么缺点吗 州 有人一再提出要求 工厂函数的用户 创建给定类型的对象,并 向其返回共享的\u ptr。此外 方便又时尚,这样的功能 也是异常安全和安全的 速度相当快,因为它可以使用 两个项目的单一分配 对象及其相应的控件 块,消除一个重要的 共享ptr结构的一部分 开销这消除了一个 有关效率的主要投诉 共享\u ptr 我知道至少有两个 你必须控制分配。这不是一个很大的api,但是一些旧的api喜欢返回必须删除的指针 没有自

使用
make_shared()
而不是使用
shared_ptr(新T)
有什么缺点吗

有人一再提出要求 工厂函数的用户 创建给定类型的对象,并 向其返回共享的\u ptr。此外 方便又时尚,这样的功能 也是异常安全和安全的 速度相当快,因为它可以使用 两个项目的单一分配 对象及其相应的控件 块,消除一个重要的 共享ptr结构的一部分 开销这消除了一个 有关效率的主要投诉 共享\u ptr


我知道至少有两个

  • 你必须控制分配。这不是一个很大的api,但是一些旧的api喜欢返回必须删除的指针
  • 没有自定义删除程序。我不知道为什么不支持这个,但它不是。这意味着您的共享指针必须使用普通的删除器

相当薄弱的地方。因此,尽量使用make_shared.

除了@deft_代码所提供的要点之外,还有一个更弱的要点:

  • 如果在给定对象的所有
    shared_ptr
    s均已失效后,使用仍在运行的
    weak_ptr
    s,则该对象的内存将与控制块一起在内存中运行,直到最后一个weak_ptr失效。换句话说,对象被销毁,但直到最后一个
    弱\u ptr
    被销毁后才解除分配
来自


make_shared()实现的另一个缺点是增加了目标代码的大小。由于此优化的实现方式,将为make_shared()使用的每种对象类型实例化一个额外的虚拟表和一组虚拟函数。

使用make shared,您无法指定如何分配和解除分配保留的对象。

如果需要,请使用
std::allocate_shared

std::vector<std::shared_ptr<std::string>> avec; 
std::allocator<std::string> aAllocator;
avec.push_back(std::allocate_shared<std::string>(aAllocator,"hi there!"));
std::vector avec;
std::分配器aAllocator;
avec.push_back(std::allocate_shared(allocator,“你好!”);
注意,向量不需要通知分配器


要制作自定义分配器,请查看此处

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

如果不使用
make_shared
,情况也是如此。唯一的区别是控制块将位于一个单独分配的内存块中。@迈克:当然不是-通常,如果对象没有共享内存,只有弱内存,那么该对象将立即被删除。我不知道控制块是否还保留着,我相信你的话。通过make_shared,控制块和对象共享一个分配,因此如果其中一个的内存仍然存在,那么它们都会这样做(尽管我猜对象被破坏了,只是内存没有释放?)。呃,是的。很抱歉当我写这篇文章时,我的另一个大脑一定很活跃。没有自定义删除器,因为只有
make_shared
本身知道如何删除对象。自定义删除器用于执行一些有趣的技巧,而不仅仅是删除,这就是为什么deft_code提到它。如果你可以添加自定义删除器,那么您也应该有定制分配器的能力;假设它会使界面变得太复杂。@MikeSeymour:从
shared\u ptr
的角度来看,是的,它需要有一个由
make\u shared()
提供的自定义删除程序,但是为
make\u shared()
的调用方提供运行自定义“sub deleter”的能力是可能的,而且可能是有用的它从
make_shared()
自己的自定义删除程序内部运行。我想说的是,它看起来是这样的:
模板共享\u ptr make_shared2(分配器a、删除程序d、参数…参数)是的,可以提供,但不是很漂亮。人们可能会想,关于共享ptr的其他主要效率抱怨是什么?异常安全是
std::make_shared
的一项非常重要的资产。尽可能使用它。@ViktorSehr互斥锁在引用计数器上,当
共享\u ptr
主要被复制时:)@Drax:Ah,所以它们是线程安全的?不知道that@Drax顺便说一句,不要介意问号,我可以用谷歌搜索:)随着编译器的发展,这种情况会持续下去吗?