首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 類別互相持有指標:雙向關聯與前向宣告

     編輯:程式設計綜合問答

程式碼結構


// 前向宣告
class B;

class A {
public:
    A() : b_ptr(nullptr) {}
    ~A() { delete b_ptr; } // 若 A 擁有 B
    void setB(B* b) { b_ptr = b; }
private:
    B* b_ptr;
};

class B {
public:
    B() : a_ptr(nullptr) {}
    ~B() { /* 不刪除 a_ptr,避免雙重釋放 */ }
    void setA(A* a) { a_ptr = a; }
private:
    A* a_ptr;
};

語意解析

模式擁有權解構責任典型場景
單向擁有A 擁有 B (unique_ptr)A 解構時刪除 B父子物件、組合關係
雙向非擁有雙方僅持有**觀察者指標** (raw ptr / weak_ptr)雙方**不刪除**對方雙向鏈表、圖節點、父子回調
共享擁有雙方 `shared_ptr`引用計數歸零自動釋放循環引用需 `weak_ptr` 打斷

現代 C++ 最佳實踐


#include 

class B; // 前向宣告

class A {
public:
    void setB(std::shared_ptr b) { b_ptr = b; }
    std::weak_ptr getB() const { return b_ptr; } // 對外暴露 weak_ptr
private:
    std::shared_ptr b_ptr; // A 共享擁有 B
};

class B {
public:
    void setA(std::weak_ptr a) { a_ptr = a; } // B 僅弱引用 A
    std::shared_ptr getA() const { return a_ptr.lock(); }
private:
    std::weak_ptr a_ptr; // 打斷循環引用
};

// 使用
auto a = std::make_shared();
auto b = std::make_shared();
a->setB(b);
b->setA(a);
// a, b 離開作用域自動釋放,無記憶體洩漏

關鍵規則

  1. **前向宣告** (`class B;`) 解決編譯期相依循環。
  2. **明確擁有權**:誰負責 `delete` / 持有 `unique_ptr`/`shared_ptr`。
  3. **循環引用必須用 `weak_ptr`** 打斷,否則 `shared_ptr` 計數永不歸零 → 記憶體洩漏。
  4. **原始指標** 僅用於**非擁有觀察**,文件註明生命週期由誰管理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved