什么是以下两者之间的区别:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
以及
std::shared_ptr<int> p = std::make_shared< int >();
我应该选择哪一个并为什么?
附言:我相当确定这个问题已经被回答过了,但我找不到类似的问题。
什么是以下两者之间的区别:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
以及
std::shared_ptr<int> p = std::make_shared< int >();
我应该选择哪一个并为什么?
附言:我相当确定这个问题已经被回答过了,但我找不到类似的问题。
两个示例都比必要的更冗长:
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:
来自微软官方文档的进一步推荐和相关示例。重点关注示例1片段:
尽可能使用 make_shared 函数在首次创建内存资源时创建 shared_ptr。make_shared 是异常安全的。它使用相同的调用为控制块和资源分配内存,从而减少构造开销。如果不使用 make_shared,则必须使用显式的 new 表达式创建对象,然后将其传递到 shared_ptr 构造函数。以下示例展示了声明和初始化 shared_ptr 以及新对象的各种方法。
从en.cppreference.com上可以看出,使用make_shared
声明std::shared_ptr<T> p(Args...)至少进行两次内存分配,这可能会产生不必要的开销。
而且,f(shared_ptr<int>(new int(42)), g())
如果g抛出异常可能导致内存泄漏。如果使用make_shared
则不存在此问题。因此,如果可能的话我建议使用make_shared
方法。
shared_ptr
和make_shared
存在问题(它们仍然在tr1
命名空间中,因此我必须定义宏来编写可移植代码使用共享指针)。我的意思是,需要额外的宏才能使用make_shared
。 - Violet Giraffeclang
现在是Mac的官方编译器,而且苹果公司不经常更新它。 - Violet Giraffe注意,使用make_shared
会限制你只能使用默认的内存分配/释放函数,因此如果你想要更多控制权,则不能使用make_shared
。换句话说,类似于
std::shared_ptr<uint8_t>(p, [](uint8_t *p){ /*user code */});
使用make_shared
是不可能的。可以使用allocate_shared
,但只能指定分配器而不能指定删除器。有时需要控制封装类的分配和删除。
std::make_shared<int>()
。 - nosidmake_shared
。有关更多信息,请参阅以下网址:http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ - nosid