【C++】智能指针 std::shared_ptr 的创建方法

两种创建方法:第一种:std::make_shared 创建;第二种:new 方法创建。

当使用 std::make_shared 创建一个 std::shared_ptr 时,C++ 的实现会在单个内存分配中同时为对象本身和与之相关的控制块(包括引用计数)分配内存。这种内存分配策略与直接使用 std::shared_ptr 的构造函数配合 new 操作符有显著的不同,后者通常涉及两个独立的内存分配:一个用于对象本身,另一个用于控制块。下面详细解释这两种方法的不同:

使用 std::make_shared

当你调用 std::make_shared 时,如:

auto ptr = std::make_lushared<SomeClass>(args...);

C++ 标准库会进行以下操作:

单个内存分配:分配足够的内存来存储 SomeClass 的实例和相关的控制块。控制块通常包括引用计数、弱引用计数和可能的其他元数据。

构造对象:在已分配的内存中的适当位置构造 SomeClass 的实例。构造函数的参数 args... 将被传递给 SomeClass 的构造函数。

初始化控制块:设置引用计数为 1,弱引用计数根据需要进行设置。

这种方法的好处是减少了内存分配的次数(从两次减少到一次),这可以提高内存分配的效率,减少内存碎片。此外,因为对象和控制块位于相邻的内存区域,可能还会改善缓存的利用率。

使用 new 操作符与 std::shared_ptr 构造函数

当你创建一个 std::shared_ptr 通过直接使用 new 操作符时,如:

std::shared_ptr<SomeClass> ptr(new SomeClass(args...));

则涉及以下步骤:

对象内存分配:使用 new 操作符分配内存并构造 SomeClass 的实例。这涉及调用 SomeClass 的构造函数,参数为 args...

解释:当使用 new SomeClass(args…) 时,首先会在堆上分配足够的内存来存储 SomeClass
类型的对象。然后,使用传递的参数 args… 来构造这个对象。这里的内存分配是专门用来存储对象实例本身的数据。

控制块内存分配:当 std::shared_ptr 构造时,它将分配一个控制块来管理对象的生命周期和存储引用计数。

解释:std::shared_ptr 除了管理对象的指针外,还需要管理与对象生命周期相关的附加信息,比如引用计数(用来追踪有多少个
shared_ptr 实例共享同一个对象)和弱引用计数(用来追踪有多少个 weak_ptr
实例被关联)。为了存储这些信息,std::shared_ptr 在创建时会在堆上分配一个控制块(control
block)。这个控制块通常包括引用计数、弱引用计数和一个析构器函数指针等。

这种方法涉及两次独立的内存分配,一次是为对象本身,另一次是为控制块,这可能导致较低的内存分配效率和更多的内存碎片。

总结
因此,std::make_shared 的单一内存分配方法提供了效率和性能上的优势。然而,如之前提到的,当需要使用自定义删除器或在某些特殊情况下管理外部资源时,直接使用 newstd::shared_ptr 的构造函数可能更合适。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值