C++ make_shared智能指针的使用

时间:2025-04-01 19:37:42

​ C++使用模板函数 std::make_shared 可以返回一个指定类型的 std::shared_ptr

1、为何使用动态内存

如果事先知道所需内存空间,使用静态内存是最简单的解决方案。

但是,在程序设计的过程中,往往会遇到需要开辟一个未知大小的内存空间,该空间根据程序所需发生大小的变化,此空间称为动态内存。

程序设计中使用动态内存的原因可能如下:

  • 程序不知道自己需要多少对象;
  • 程序不知道所需对象的准确类型;
  • 程序需要在多个对象之间共享数据。

2、make_shared用法

make_shared在动态内存中分配一个对象并初始化它, 返回指向此对象的shared_ptr,与智能指针一样,make_shared定义在头文件memory中;

当要用make_shared时,必须指定想要创建的对象类型,定义方式与模板类相同,在函数名之后跟一个尖括号,在其中给出类型;

make_shared<int>p3 = make_shared<int>(42)
//一般采用auto定义一个对象来保存make_shared的结果
auto p1 = make_shared<int>(42);    

3、shared_ptr用法

可以指向特定类型的对象,用于自动释放所指的对象。

(1)优点
  • 效率更高shared_ptr 需要维护引用计数的信息,

    • 强引用, 用来记录当前有多少个存活的 shared_ptrs 正持有该对象. 共享的对象会在最后一个强引用离开的时候销毁( 也可能释放)
    • 弱引用, 用来记录当前有多少个正在观察该对象的 weak_ptrs. 当最后一个弱引用离开的时候, 共享的内部信息控制块会被销毁和释放 (共享的对象也会被释放, 如果还没有释放的话)

    内存分配的动作, 可以一次性完成.

    这减少了内存分配的次数, 而内存分配是代价很高的操作

  • 异常安全

(2)缺点
  • 构造函数是protected或private时,无法使用 make_shared

  • 对象的内存可能无法及时回收

    weak_ptr 会保持控制块(强引用, 以及弱引用的信息)的生命周期, 而因此连带着保持了对象分配的内存, 只有最后一个 weak_ptr 离开作用域时, 内存才会被释放. 原本强引用减为 0 时就可以释放的内存, 现在变为了强引用, 若引用都减为 0 时才能释放, 意外的延迟了内存释放的时间。