解决shared_ptr的循环引用
创作时间:
作者:
@小白创作中心
解决shared_ptr的循环引用
引用
CSDN
1.
https://blog.csdn.net/guaiguaiyalj/article/details/143248681
在实现智能指针shared_ptr
中有一个问题就是循环引用的问题,对于循环引用看下面的图来理解:
node1
和node2
两个智能指针对象指向两个节点,引用计数变成1,我们不需要手动delete
。node1
的_next
指向node2
,node2
的_prev
指向node1
,引用计数变成2(因为我们定义的结构中_next
和_prev
也是shared_ptr
的智能指针对象)。node1
和node2
析构,引用计数减1,但是_next
还指向下一个节点。_prev
还指向上 一个节点。- 也就是说
_next
析构了,node2
的引用计数变为0,就释放了;同理_prev
析构了,node1
就释放了。 - 但是
_next
属于node1
的成员,node1
释放了,_next
才会析构,而node1
由_prev
管理,_prev
属于node2
成员,所以这就叫循环引用,谁也不会释放。
再换个角度理解:
假如这里只有一个指向:node1->_next = node2
;这样node1
的计数为1,node2
的计数为2,node1
和node2
析构就会让node1
的计数见减为0,node2
减为1,然后node1
计数为0释放,同时也会让node1
的成员_next
析构,_next
的析构就会导致node2
的计数减为0,这样node2
也会释放,就不会有循环引用的问题。
我们这次要解决循环引用,就要把结构体中的_next
和_prev
不要计数就可以解决,那样node1
和node2
析构时资源也就释放了。解决方案:在引用计数的场景下,把节点中的_prev
和_next
改成weak_ptr
就可以了。原理就是,node1->_next = node2
和node2->_prev = node1
时,weak_ptr
的_next
和 _prev
不会增加node1
和node2
的引用计数。
template<class T>
class weak_ptr
{
public:
weak_ptr()
:_ptr(nullptr)
{}
weak_ptr(const shared_ptr<T>& sp)
:_ptr(sp.get())
{}
weak_ptr<T>& operator=(const shared_ptr<T>& sp)
{
_ptr = sp.get();
return *this;
}
// 像指针一样
T& operator*(){return *_ptr;}
T* operator->(){return _ptr;}
private:
T* _ptr;
};
这里拷贝构造和赋值都是对shared_ptr
对象,也就是说只需要拷贝构造和赋值shared_ptr
对象的_ptr
就可以了。因为这是不同的类,_ptr
是shared_ptr
中的私有成员,不可访问,有两种方式可以实现:1、友元类;2、在shared_ptr
中写一个公有的成员函数get
来获取_ptr
。
热门推荐
面对乙状结肠癌T3N3ng/ml应该如何应对
如何评估基金投资产品的投资表现和风险?这种评估如何影响投资决策?
红茶与陈皮的奇妙搭配:功效、禁忌与健益处一览无余
深孔加工技术研究综述及发展趋势
枪管为什么不能铸造,非要用铁棒钻出来?
合村并镇继续推进:平房换楼房,将现4合1、6合1、10合1大村庄
村民会议发言:乡村治理的有效途径
扰民起诉需要什么证据?法院起诉流程及影响全解析
合租室友晚上11点后还用洗衣机,算扰民行为吗?
太平天国猛将林凤祥北伐之谜:辉煌战功背后的痛苦挣扎
太平天国北伐军主帅林凤祥:从金田起义到凌迟处死的悲壮人生
文件访问被拒绝,原来可以这样处理!
珠海新能源产业发展现状及前景分析
房贷还款和利息计算方法及注意事项
吟诗入乐,感受古诗词的另一种美
先导智能递交港股上市申请 “A+H”布局巩固领先优势
樗里疾:战国秦国的智囊与名将
樗里疾:战国秦国的智囊与名将
'除湿的茶有哪些:最快的排湿茶和祛湿茶品种推荐'
《柳叶刀》中风醒脑液双盲试验作者:没想过无效
王毅传中造点朱辰杰主罚命中 上海申花1:0广州队
小规模验证商业模式:如何测试和优化你的商业想法
金价一举突破2900美元!节后闲钱还能买吗?听听他们的回答…
一根烤面筋的热量
面筋要做哪些检测?面筋检测项目和标准一览
道和术分别是指什么
减肥过程体重秤(减肥过程体重秤会变重吗)
如何识别并解决物联网卡流量虚标问题?
氯化钾溶液的作用
《阿鲁卡多巅峰对决中的传奇角色探析》