91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中的循環引用實例

發布時間:2021-08-19 20:20:49 來源:億速云 閱讀:184 作者:chen 欄目:編程語言

本篇內容介紹了“C++中的循環引用實例”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

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

C++中的循環引用實例

//
// 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析構如此就導致兩個指針指向的對象沒有析構釋放內存,這就是循環引用導致的內存問題。

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

C++中的循環引用實例

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

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

//
// main.cpp
// test
//
// Created by 杜國超 on 17/9/9.
// Copyright &copy; 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++中的循環引用實例

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

“C++中的循環引用實例”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

家居| 乌兰浩特市| 潍坊市| 手机| 南召县| 武平县| 阿克苏市| 仁化县| 汾西县| 收藏| 淮安市| 贡嘎县| 临江市| 商洛市| 富川| 安泽县| 上饶市| 水城县| 兰西县| 安图县| 漠河县| 南雄市| 蓬安县| 丰顺县| 宁国市| 仪征市| 怀安县| 吐鲁番市| 新河县| 体育| 茶陵县| 和林格尔县| 普洱| 沙洋县| 怀仁县| 治多县| 柘荣县| 且末县| 平顶山市| 阜平县| 高淳县|