【问题标题】:Preferred way of creating shared pointers创建共享指针的首选方式
【发布时间】:2016-10-06 06:29:36
【问题描述】:

documentation 声明std::make_shared<T> 通常会同时为T 和智能指针的控制块分配内存,而std::shared_pointer<T>(new T) 则执行两次分配。这是否意味着它更有效,因此如果可能,应该始终使用std::make_shared

关于 Qt 等效项的相同问题 - QSharedPointer。根据docsQSharedPointer 内部结构和对象在一次内存分配中分配,这有助于减少长时间运行的应用程序中的内存碎片。这是否意味着QSharedPointer<T>::create() 是首选?

class MyClass {};

QSharedPointer<MyClass> ptr1 = QSharedPointer<MyClass>::create();   // better
QSharedPointer<MyClass> ptr2(new MyClass);  // worse

【问题讨论】:

    标签: c++ qt smart-pointers


    【解决方案1】:

    std::make_shared 几乎在所有情况下都是首选。然而,如果你使用弱指针,你很容易陷入“内存泄漏”的境地,即内存保留的时间比你乍一看要长得多(毕竟shared_ptrs 已经消失了)。

    只要有一个std::weak_ptrstd::shared_ptr 控制块相关联,该控制块就必须保留。由于std::make_shared 为控制块和数据创建了一个单独的内存分配,如果控制块保留,数据也必须保留。使用std::shared_ptr,有两个分配,因此可以独立清理。

    因此,如果您不使用std::weak_ptr(以下附加注意事项),绝对总是更喜欢std::make_shared,以获得包括分配数量和异常安全性在内的好处。如果您使用std::weak_ptr,您的设计一定要考虑周到。

    Modern Effective C++ 第 4 章专门介绍如何/何时使用不同的智能指针。这是一本简明的书,供现有 c++ 程序员了解 c++11/14 中的新功能,包括智能指针。

    编辑:正如@midor 提到的,您在使用std::make_shared 时也根本没有提供自定义删除器的选项。此外,如果类型 T 有不同的构造函数,它们可以用相同的类型调用,但一个用() 调用,一个用{} 调用,那么它总是更喜欢用() 调用的那个。例如std::make_shared&lt;std::vector&gt;(10,10) 调用std::vector(10,10) 而不是std::vector{10,10}

    【讨论】:

    • std::make_shared 在异常安全方面有什么好处?
    • 既然您参考了这本书,请不要忘记提及另一种无法选择的情况:指定自定义删除器时
    • 可能值得澄清的是,这并不是真正的“内存泄漏”,而只是一个较大的内存块被弱指针“持有”的情况。与使用显式 new 创建共享指针的情况相比,内存的释放时间晚(或晚得多)。
    • @Dadam 很容易编写代码,在同一行抛出异常会导致内存被分配,但永远不要将其放入 shared_ptr 构造函数以供以后删除:f(std ::shared_ptr(new int(42)), g()) 如果 g() 抛出,new int(42) 可能已经运行。
    • @AnT 我认为在将其放在引号中并稍后详细说明为什么要保留内存的确切细节之间,它既可以清晰地了解问题的高级视图,也可以提供详细信息关于如何避免它。不过,我对第一段稍作改动。
    猜你喜欢
    • 2015-03-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多