国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++中的循環引用

2020-01-26 13:55:40
字體:
來源:轉載
供稿:網友

雖然C++11引入了智能指針的,但是開發人員在與內存的斗爭問題上并沒有解放,如果我門實用不當仍然有內存泄漏問題,其中智能指針的循環引用缺陷是最大的問題。

//// main.cpp// test//// Created by 杜國超 on 17/9/9.// Copyright © 2017年 杜國超. All rights reserved.//#include <iostream>#include <memory>#include <vector>using namespace std;class CObjB;class CObjA{public:  CObjA() { cout << "CObjA Constructor..." << endl; }  ~CObjA() { cout << "CObjA Destructor..." << endl; }  shared_ptr<CObjB> m_pb; // 在A中引用B};class CObjB{public:  CObjB() { cout << "CObjB Constructor..." << endl; }  ~CObjB() { cout << "CObjB Destructor..." << endl; }  shared_ptr<CObjA> m_pa; // 在B中引用A};int main() {  shared_ptr<CObjA> tmpPa = make_shared<CObjA>();  shared_ptr<CObjB> tmpPb = make_shared<CObjB>();  tmpPa->m_pb = tmpPb;  tmpPb->m_pa = tmpPa;  std::cout << "CObjA referencr num:" << tmpPa.use_count() << endl;  std::cout << "CObjB referencr num:" << tmpPb.use_count() << endl;//  tmpPa->m_pb.reset();//  tmpPb->m_pa.reset();//  std::cout << "CObjA referencr num:" << tmpPa.use_count() << endl;//  std::cout << "CObjB referencr num:" << tmpPb.use_count() << endl;}

我們可以看到在出main函數作用域之前兩個指針指向的內存并沒有釋放(指針指向的對象沒有調用析構函數),我門把當前的引用數打印出來為2這個沒有問題,為什么在函數結束時沒有調用對象的析構函數呢?這就好像多線程之間的死鎖一樣,對象a想要析構但是發現對象b引用了自己所以就等待對象b析構不再引用自己,而b想要析構卻發現對象a引用了自又等待a析構如此就導致兩個指針指向的對象沒有析構釋放內存,這就是循環引用導致的內存問題。

如何證明這個結論呢,我們手動釋放掉兩個對象對對方的引用,就可以解除循環引用關系,正確析構對象了(把注釋部分代碼打開)。運行結果:

我門可以看到,調用reset函數釋放引用關系后,指針的引用計數變為一,等到函數運行結束,兩個shared指針生命周期結束調用析構函數,對象的引用計數減為0,對象內存釋放。

但是如果每次都要手動解除引用來解決循環引用,那么智能指針似乎變成了傻子指針了,這時候還有一個東西能解決,那就是weak_ptr,它不會改變所共享的shared_ptr的引用計數,即使我門可以通過該指針訪問它所指向的對象。 

//// main.cpp// test//// Created by 杜國超 on 17/9/9.// Copyright © 2017年 杜國超. All rights reserved.//#include <iostream>#include <memory>#include <vector>using namespace std;class CObjB;class CObjA{public:  CObjA() { cout << "CObjA Constructor..." << endl; }  ~CObjA() { cout << "CObjA Destructor..." << endl;}  void Say() {cout << "CObjA Say..." << endl; }  shared_ptr<CObjB> GetPb() {    return m_pb.lock();  }public:  weak_ptr<CObjB> m_pb; // 在A中引用B};class CObjB{public:  CObjB() { cout << "CObjB Constructor..." << endl; }  ~CObjB() { cout << "CObjB Destructor..." << endl; }  void Say() {cout << "CObjB Say..." << endl; }  shared_ptr<CObjA> GetPa() {    return m_pa.lock();  }public:  weak_ptr<CObjA> m_pa; // 在B中引用A};int main() {  shared_ptr<CObjA> tmpPa = make_shared<CObjA>();  shared_ptr<CObjB> tmpPb = make_shared<CObjB>();  tmpPa->m_pb = tmpPb;  tmpPb->m_pa = tmpPa;  std::cout << "CObjA referencr num:" << tmpPa.use_count() << endl;  std::cout << "CObjB referencr num:" << tmpPb.use_count() << endl;  if (tmpPa->GetPb()!= NULL){    tmpPa->GetPb()->Say();  }  if (tmpPb->GetPa()!= NULL){    tmpPb->GetPa()->Say();  }}

這樣就得到我門想要的結果了。最后說一句雖然智能指針帶來了很多方便,但是也要小心使用它仍然有很多坑等著我門,以后再作詳述。

總結

以上所述是小編給大家介紹的C++中的循環引用,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 台北市| 藁城市| 天峻县| 吉安市| 北海市| 勐海县| 普宁市| 沂南县| 柳河县| 化州市| 城固县| 北辰区| 宁明县| 天柱县| 英超| 阳东县| 武冈市| 丰原市| 望江县| 郓城县| 江源县| 青州市| 民勤县| 英超| 塔河县| 衡阳县| 淄博市| 安阳县| 寿宁县| 家居| 化州市| 犍为县| 淄博市| 松江区| 定结县| 乐平市| 海晏县| 邯郸市| 日喀则市| 和顺县| 盐城市|