// 前向宣告
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` 打斷 |
#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 離開作用域自動釋放,無記憶體洩漏