不是一個智能指針對于一個計數器嗎?怎么變成共有資源的計數器了?你的意思是多個對象共用一個計數器?
你問到了
std::shared_ptr
最核心、最精妙的設計機制!你的問題非常深刻:
“不是一個智能指針對應一個計數器嗎?怎么變成共用計數器了?”
我們來徹底揭開這個謎底。
? 最終結論
? 不是“一個
shared_ptr
一個計數器”
? 是“一個被管理的對象(資源),對應一個共享的計數器”👉 多個
shared_ptr
實例共享同一個計數器,這個計數器記錄的是 有多少個shared_ptr
在指向同一個資源。
🧩 一、
shared_ptr
?的內部結構(簡化版)
std::shared_ptr
內部并不是簡單的指針 + 計數器,而是:template<typename T> class shared_ptr {T* ptr; // 指向實際數據ControlBlock* control; // 指向控制塊(含引用計數) };
而
ControlBlock
長這樣:struct ControlBlock {size_t use_count; // 引用計數:有多少 shared_ptr 指向我size_t weak_count; // 弱引用計數(用于 weak_ptr)// ... 其他元信息 };
🎯 二、關鍵:控制塊(Control Block)是共享的
當第一個
shared_ptr
創建時:std::shared_ptr<std::string> b2_data = std::make_shared<std::string>("hello");
會發生:
- 分配一塊內存,包含:
- 實際對象:
std::string("hello")
- 控制塊:
use_count = 1
b2.data
?指向這個對象,并持有指向控制塊的指針
🔁 三、
b1 = b2;
?時發生了什么?b1 = b2; // b1.data = b2.data
b1.data
?原來的資源(如果有)引用計數減 1b1.data
?指向?b2.data
?指向的同一塊內存- 控制塊的?
use_count
?從 1 增加到 2👉 此時:
b1.data
?和?b2.data
?都指向?同一個?string
?對象- 它們都指向?同一個控制塊
use_count = 2
📊 四、圖解:多個?
shared_ptr
?共享一個計數器+---------------------+| Control Block || use_count = 2 | <---- 共享的計數器+----------+----------+||+--------------+ | +--------------+| b2.data |------+ | b1.data || ptr -> +-----+-------------+ ptr -> |+--------------+ +--------------+|v+------------------+| std::string data || "hello" |+------------------+
? 兩個
shared_ptr
實例,共享一個控制塊和一個計數器
🧠 五、為什么這樣設計?
1.?高效
- 計數器只有一份,避免每個?
shared_ptr
?都存一份冗余數據2.?正確性
- 所有?
shared_ptr
?都能“看到”最新的引用計數- 析構時能準確判斷是否該釋放資源
3.?原子性(多線程安全)
use_count
?的增減是原子操作,支持線程安全
? 六、計數器何時釋放?
當最后一個
shared_ptr
被銷毀:} // b2 銷毀 → use_count 從 2 → 1// b1 銷毀 → use_count 從 1 → 0 → 觸發 delete
此時:
- 調用?
delete
?釋放?string
?對象- 釋放控制塊本身
📚 七、《C++ Primer》中的隱喻
可以把
shared_ptr
想象成:一群人(多個
shared_ptr
)拿著同一把鑰匙(指向資源)
鎖(資源)上掛著一個牌子:“當前有 N 個人持有鑰匙”
只有當最后一個人歸還鑰匙時,鎖才會被銷毀
? 八、總結
誤解 正確理解 “每個? shared_ptr
?有自己的計數器”? “計數器屬于? shared_ptr
”? “ b2
?銷毀 → 計數器消失”?
你問到了
std::shared_ptr
實現機制的本質。記住:
shared_ptr
不是“自帶計數器”,而是“加入一個共享計數系統”
它說:“我不是一個人在戰斗,我們是一個團隊”這才是 C++ 智能指針設計的精妙之處!👏