shared_ptr相关

shared_ptr

定义

一种 共享对象所有权 的智能指针,允许多个shared_ptr拥有相同的对象。

对象销毁时机:(引用计数归零)

1. 最后一个拥有该对象的shared_ptr 被销毁
2. 最后一个有用该对象的shared_ptr 转移对象所有权(通过operator= 或 reset()方法 )

对象的销毁方法:

1. delete-expression(包括delete ,delete[] )
2. 构造shared_ptr时 自定义的删除器 

允许为空:

shared_ptr 允许为空,不拥有任何manage对象 。

转移所有权:

对象的所有权只能通过 copy构造和 copy 赋值来共享。 而使用 shared_ptr 的原始指针 来构造新的shared_ptr 会导致 未定义行为,不允许隐式构造。

具体实现:

以 shared_ptr< string > p = make_shared< string >(10,‘9’) 为例 。
在实现shared_ptr的经典方法中, 只有两个指针:
1. 指向数据内存空间的原始指针(内存中"9999999999"所保存的位置,可通过get()方法获取 地址),
2. 指向控制块的指针 。 控制块是一个动态分配的对象,维护在上,包含:1.指向manage对象的指针(指向string 对象) , 2.删除器 3.分配器 4.指向同一个manage对象的shared_ptr数量 5. 指向同一个manage对象的weak_ptr数量。

shared_ptr本身的线程安全性:

  1. 多线程中不同shared_ptr执行 copy构造和copy赋值等函数时 ,不需要额外的同步机制 。

  2. 如果其中一个访问 非const 成员函数,则会发生数据竞争。 shared_ptr重载了原子函数 来防止数据竞争。

    1. 引用计数增减 线程安全

    为了满足线程安全要求,引用计数器通常使用std::atomic::fetch_add和std::memory_order_relax的等原子操作 更新堆上的 控制块信息 。

    2. 修改指向时

    2.1 多线程操作同一个shared_ptr对象 - 不安全

    如thread 执行func(shared_ptr< A > &sp): 其中有 sp = other_sp ;

    一个线程中要修改shared_ptr 的指向, sp原来指向的引用计数需要减1 , other_sp指向的引用计数需要加1。即多个线程都在修改sp时可能出现问题,这些操作并不是原子操作。例如: 在引用计数在减1的时候,其内部的指向已经被其他线程修改了。引用计数的异常会导致某些托管对象被提前析构,后续在使用到该数据的时候触发core dump。

    2.2 多线程操作不同shared_ptr对象 - 安全

    如thread 执行func(shared_ptr< A > sp): 其中有 sp = other_sp ; 这里传值涉及到拷贝构造,已不是同一个shared_ptr对象。

    这时候每个线程中的sp,管理的是同一份数据,使用同一个引用计数。当发生多线程修改sp指向时,原子操作的引用计数增减,保证了导致线程安全。

参考1:https://zhuanlan.zhihu.com/p/416289479
参考2:https://en.cppreference.com/w/cpp/memory/shared_ptr

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值