我不使用std :: make_shared的情况有哪些?

7
根据我所做的研究,似乎使用std::make_shared构建std::shared_ptr是首选方法。具体原因如下:
  1. 与使用new相比,它仅执行一次内存分配。
  2. 如果传递给make_shared的构造函数抛出异常,则不会像使用new那样泄漏。
我的问题是,假设我想要一个shared_ptr,我是否应该始终使用make_shared,还是有一些情况下更适合使用new

如果shared_ptr构造函数抛出异常,shared_ptr<int>(new int)不会泄漏内存;这是您的第二点对我来说似乎意味着这一点。 - Simple
5个回答

6
由于计数器和对象共享相同的分配,它们也共享相同的释放。计数器必须持续到最后一个 shared_ptr 和 weak_ptr 被清空。如果您有一个具有长期 weak_ptr 的大型对象(或许多小型对象),如果通过 make_shared 分配 shared_ptr,这可能会导致内存争用。
其次,如果您有一个第三方 API,该 API 会将指针或资源句柄交给您,并且可能具有自己的处理功能,则在每种情况下都不适合使用 make_shared 并且可能无法使用。创建自己的 make_ 函数可以使混乱的细节远离并解决此问题,并处理异常角落情况。
最后,虽然 shared_ptr 非常棒,但它们也过于强大。很多时候我想要一个 unique_ptr 或甚至是 boost::scoped_ptr,或者类似的 intrusive 引用计数指针来表示所有权。仅当实际涉及资源的共享所有权时才应使用 shared_ptr:因为它很“容易”,所以随意使用它往往会导致资源等价于意大利面条代码。

4
最后一段得到额外加分。虽然直接问题没有涉及,但在这种情况下不能太多次地强调。 - Christian Rau

2
您可能需要处理返回动态分配对象的旧代码。在这种情况下,您需要使用带指针参数的 std::shared_ptr<T> 构造函数。虽然不推荐使用 std::make_shared,但它确实允许您在旧代码中使用所有 std::shared_ptr<T> 的好处。
我知道这与直接使用 newstd::shared_ptr<T> 构造函数并不完全相同,但这是一个有效使用 std::shared_ptr<T> 的用例,在其中无法利用 make_shared

1
我对你的问题解释有些不确定。我假设使用shared_ptr<T>是有道理的;我只能在Yakk上同意为什么你不想使用shared_ptr。有一种情况下,你不能使用make_sharedallocate_shared来构造shared_ptr,但你需要使用相应的构造函数:如果你需要传递自定义删除器,请参见shared_ptr的构造函数(3)和(4)

0

我在使用make_shared时遇到了问题,因为该类具有私有构造函数(来自静态工厂方法)。我认为这个问题没有简单的解决方案。


我认为有一个关于这个的缺陷被提出了; 你是否能够将make_shared设置为友元函数?标准不清楚它是否会起作用。 - Simple
我做了一个解决方法,让你可以使用一个“私有”的构造函数来调用make_shared:http://ideone.com/O93w6o - Simple

0
我应该总是使用make_shared,还是有一些情况下使用new更好?
当我们在存储由其他人分配的裸指针时,不允许使用make_shared。它只能调用public构造函数。但是,在某些编译器中,有关于使用make_shared访问受保护构造函数的报告类似于这样

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接