std::shared_ptr 初始化:make_shared<Foo>() vs shared_ptr<T>(new Foo)

新手上路,请多包涵

有什么区别:

 std::shared_ptr<int> p = std::shared_ptr<int>( new int );

std::shared_ptr<int> p = std::make_shared< int >();

?

我应该更喜欢哪一个,为什么?

PS很确定这一定已经回答了,但我找不到类似的问题。

原文由 Violet Giraffe 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 833
2 个回答

这两个例子都比必要的更冗长:

 std::shared_ptr<int> p(new int);  // or '=shared_ptr<int>(new int)' if you insist
auto p = std::make_shared<int>(); // or 'std::shared_ptr<int> p' if you insist

有什么不同?

主要区别在于第一个需要两个内存分配:一个用于托管对象( new int ),另一个用于引用计数。 make_shared 应该分配一个内存块,并在其中创建两者。

我应该更喜欢哪一个,为什么?

您通常应该使用 make_shared 因为它更有效。如另一个答案所述,它还避免了内存泄漏的任何可能性,因为您永远没有指向托管对象的原始指针。

但是,正如评论中所指出的,如果仍然有弱指针阻止共享计数被删除,那么当对象被销毁时,内存将不会被释放,这有一个潜在的缺点。


编辑 2020/03/06:

进一步的建议还来自带有相关示例的 官方 Microsoft 文档。继续关注 示例 1 代码段:

首次创建内存资源时,尽可能使用 make_shared 函数创建 shared_ptr。 make_shared 是异常安全的。它使用相同的调用为控制块和资源分配内存,从而减少了构造开销。如果不使用 make_shared,则必须使用显式 new 表达式来创建对象,然后再将其传递给 shared_ptr 构造函数。以下示例显示了声明和初始化 shared_ptr 以及新对象的各种方法。

原文由 Mike Seymour 发布,翻译遵循 CC BY-SA 4.0 许可协议

来自 en.cppreference.com

相反,声明 std::shared_ptr<T> p(new T(Args...)) 执行至少两次内存分配,这可能会产生不必要的开销。

此外, 如果 g 抛出异常f(shared_ptr<int>(new int(42)), g()) 会导致内存泄漏。 如果使用 make_shared 则不存在此问题。

因此,如果可能,我会推荐 make_shared 方法。

原文由 Adri C.S. 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题