有什么区别:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
和
std::shared_ptr<int> p = std::make_shared< int >();
?
我应该更喜欢哪一个,为什么?
PS很确定这一定已经回答了,但我找不到类似的问题。
有什么区别:
std::shared_ptr<int> p = std::shared_ptr<int>( new int );
和
std::shared_ptr<int> p = std::make_shared< int >();
?
我应该更喜欢哪一个,为什么?
PS很确定这一定已经回答了,但我找不到类似的问题。
这两个例子都比必要的更冗长:
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 以及新对象的各种方法。
相反,声明std::shared_ptr<T> p(new T(Args...))
执行至少两次内存分配,这可能会产生不必要的开销。
此外,f(shared_ptr<int>(new int(42)), g())
如果 g 抛出异常,可能会导致内存泄漏。如果使用 make_shared 则不存在此问题。
所以make_shared
如果可能的话,我会推荐这种方法。
请注意,这会make_shared
限制您使用默认分配/解除分配功能,因此如果您想拥有更多控制权,make_shared
则不是一种选择。换句话说,像
std::shared_ptr<uint8_t>(p, [](uint8_t *p){ /*user code */});
不可能使用make_shared
. 可以allocate_shared
改为使用,但只能指定分配器,而不是删除器。有时需要控制包装类的分配和删除。