將引用計數與被管理對象指針解耦,分別封裝為 UseCount 計數類與 Point 業務類,智能指針 SmartPoint 組合兩者,實現共享所有權語義。
Pointclass Point {
public:
Point() : m_x(0), m_y(0) {}
Point(int& x, int& y) : m_x(x), m_y(y) {}
Point(const Point& other) : m_x(other.m_x), m_y(other.m_y) {}
~Point() { cout << "Point 析構" << endl; }
int GetX() const { return m_x; }
int GetY() const { return m_y; }
void SetX(int x) { m_x = x; }
void SetY(int y) { m_y = y; }
private: int m_x, m_y;
};
UseCount關鍵點:
*m_iUseReAttach 判斷「舊計數歸零後重新接管新計數」場景(賦值操作核心)class UseCount {
public:
UseCount() : m_iUse(new int(1)) {}
UseCount(const UseCount& other) : m_iUse(other.m_iUse) { ++*m_iUse; }
UseCount& operator=(UseCount& other) {
if (this == &other) return *this;
++*other.m_iUse; // 右側先增
if (--*m_iUse == 0) delete m_iUse; // 左側後減,歸零釋放
m_iUse = other.m_iUse;
return *this;
}
~UseCount() { if (--*m_iUse == 0) delete m_iUse; }
bool ReAttach(UseCount& other) { // 用於 SmartPoint 賦值
++*other.m_iUse;
if (--*m_iUse == 0) { delete m_iUse; m_iUse = other.m_iUse; return true; }
m_iUse = other.m_iUse; return false;
}
int GetUseNum() const { return *m_iUse; }
private: int* m_iUse;
};
SmartPointclass SmartPoint {
public:
SmartPoint() : m_Point(new Point()) {}
SmartPoint(int x, int y) : m_Point(new Point(x, y)) {}
SmartPoint(const Point& p) : m_Point(new Point(p)) {}
SmartPoint(SmartPoint& other) : m_Point(other.m_Point), m_UseCount(other.m_UseCount) {}
SmartPoint& operator=(SmartPoint& other) {
if (this == &other) return *this;
if (m_UseCount.ReAttach(other.m_UseCount)) delete m_Point; // 舊對象無人引用則刪除
m_Point = other.m_Point;
return *this;
}
void SetX(int x) { m_Point->SetX(x); }
void SetY(int y) { m_Point->SetY(y); }
int GetX() const { return m_Point->GetX(); }
int GetY() const { return m_Point->GetY(); }
void GetUseNum() const { cout << "use number is " << m_UseCount.GetUseNum() << endl; }
~SmartPoint() { if (m_UseCount.GetUseNum() == 1) delete m_Point; }
private:
Point* m_Point;
UseCount m_UseCount; // 值語義,隨 SmartPoint 生命週期
};
int main() {
SmartPoint* PA = new SmartPoint();
SmartPoint* PB = new SmartPoint(*PA); // 拷構,計數=2
SmartPoint* PC = new SmartPoint();
*PC = *PA; // 賦值,PA/PC 共享,PB 仍共享原對象 → 計數=3
PC->GetUseNum(); // 3
PA->GetUseNum(); // 3
delete PA; // 計數遞減為 2,對象存活
PC->GetUseNum(); // 2
delete PB; // 計數遞減為 1
PC->GetUseNum(); // 1
delete PC; // 計數歸零,觸發 Point 析構
}
use number is 3 use number is 3 use number is 2 use number is 1 Point 析構函數調用了
完美演示了共享所有權:最後一個 SmartPoint 析構時釋放 Point。
std::shared_ptr(C++11)、std::make_shared,內部採用控制塊優化內存佈局,並實現了線程安全引用計數(原子操作)。shared_ptr 循環引用、雙重釋放等高級問題。本文轉載自 “風清揚song” 博客,原文地址:https://2309998.blog.51cto.com/2299998/1304175