Boost.shared_ptr陷阱

本文列举了17个使用Boost.shared_ptr时需要注意的陷阱,包括避免多个shared_ptr管理同一对象导致的内存问题、防止this指针重复管理、处理循环引用、避免在函数参数中直接创建shared_ptr、正确使用shared_from_this、处理非new对象、多线程环境下引用计数的影响、使用shared_array和删除器、分配器的使用以及weak_ptr的合法性检查等。每个陷阱都给出了详细的解释和示例,提醒开发者在使用shared_ptr时要谨慎操作,以防止内存泄漏和其他潜在问题。
条款1:不要把一个原生指针给多个shared_ptr管理
int* ptr = new int;
shared_ptr<int> p1(ptr);
shared_ptr<int> p2(ptr); //logic error
ptr对象被删除了2次
这种问题比喻成“二龙治水”,在原生指针中也同样可能发生。
 
条款2:不要把this指针给shared_ptr
class Test{
public:
    void Do(){  m_sp =  shared_ptr<Test>(this);  }
private:
    shared_ptr<Test> m_member_sp;
};
 
Test* t = new Test;
shared_ptr<Test> local_sp(t);
p->Do();
 
发生什么事呢,t对象被删除了2次!
t对象给了local_sp管理,然后在m_sp =  shared_ptr<Test>(this)这句里又请了一尊神来管理t。
这就发生了条款1里“二龙治水”错误。
 
条款3:shared_ptr作为被保护的对象的成员时,小心因循环引用造成无法释放资源。
 
对象需要相互协作,对象A需要知道对象B的地址,这样才能给对象B发消息(或调用其方法)。
设计模式中有大量例子,一个对象中有其他对象的指针。现在把原生指针替换为shared_ptr.
 
假设a对象中含有一个shared_ptr<B>指向b对象;假设b对象中含有一个shared_ptr<A>指向a对象
并且a,b对象都是堆中分配的。很轻易就能与他们失去最后联系。
考虑某个shared_ptr<A> local_a;是我们能最后一个看到a对象的共享智能指针,其use_count==2,
因为对象b中持有a的指针。所以当local_a说再见时,local_a只是把a对象的use_count改成1。
同理b对象。然后我们再也看不到a,b的影子了,他们就静静的躺在堆里,成为断线的风筝。
 
解决方案是:Use weak_ptr to "break cycles."(boost文档里写的)或者显示的清理
 
条款4:不要在函数实参里创建shared_ptr
 
function ( shared_ptr<int>(new int), g( ) );  //有缺陷
可能的过程是先new int,然后调g( ),g( )发生异常,shared_ptr<int>没有创建,int内存泄露
 
shared_ptr<int> p(new int());
f(p, g());  //Boost推荐写法
 
条款5:对象内部生成shared_ptr
 
前面说过,不能把this指针直接扔给shared_ptr. 但是没有禁止在对
共享指针(shared_ptr)是C++中的一种智能指针,用于管理动态分配的内存。共享指针使用引用计数的方式来管理内存的生命周期,每当有一个共享指针指向某个对象,该对象的引用计数就会加1。当引用计数为0时,表示没有任何共享指针指向该对象,内存会被自动释放。 共享指针可以通过赋值操作将一个共享指针与另一个共享指针关联起来,这时它们会共享同一块内存。如果直接使用地址值赋值给共享指针,各个共享指针将独立存在,不会关联起来。 另外,共享指针还可以接收一个删除器(deleter)函数来管理对象的释放。删除器函数可以自定义,用于在共享指针释放内存时执行一些额外的操作。 使用共享指针可以通过make_shared函数来分配内存和进行值初始化。make_shared函数可以分配指定类型大小的内存,并进行值初始化。返回的是一个shared_ptr类型的对象,可以直接赋值给共享指针变量。例如,make_shared<int>(100)会分配一块int类型大小的内存,并初始化为100,然后返回一个shared_ptr<int>类型的对象,可以直接赋值给共享指针变量sp。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [android::sp和boost::shared_ptr设计模式区别](https://blog.csdn.net/zhangxinjieli3/article/details/80503869)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [shared_ptr的使用和陷阱](https://blog.csdn.net/River_Lethe/article/details/78734879)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值