std::shared_ptr 是 c++++ 中用于管理動態分配對象的智能指針,其核心機制是引用計數。1. 它允許多個 shared_ptr 共享同一個對象,當最后一個 shared_ptr 被銷毀或重置時,對象會被自動刪除;2. 定義 shared_ptr 最推薦的方法是使用 std::make_shared 函數,它在分配內存的同時初始化對象并創建智能指針;3. 使用 shared_ptr 時需要注意避免混用裸指針、防止循環引用(可使用 std::weak_ptr 解決)以及考慮其性能開銷;4. 常見使用場景包括共享資源管理、容器中保存動態對象以及回調函數中傳遞對象以防止提前釋放。
std::shared_ptr 是 c++ 中智能指針的一種,用來管理動態分配的對象(比如用 new 創建的對象),它通過引用計數的方式自動管理內存的釋放。簡單來說,就是多個 shared_ptr 可以共享同一個對象,當最后一個指向該對象的 shared_ptr 被銷毀或重置時,對象會被自動刪除。
什么是 std::shared_ptr?
shared_ptr 的核心機制是引用計數。每當一個新的 shared_ptr 指向某個對象時,引用計數加一;當某個 shared_ptr 不再指向這個對象(比如被銷毀或賦值為其他對象)時,引用計數減一。當引用計數變為0時,說明沒有 shared_ptr 在使用這個對象了,系統就會自動釋放這塊內存。
這種機制有效避免了內存泄漏,也比手動調用 delete 更安全。
立即學習“C++免費學習筆記(深入)”;
如何定義一個 std::shared_ptr?
定義 shared_ptr 最常用的方法是使用 std::make_shared 函數,這是推薦的做法:
auto ptr = std::make_shared<int>(42);
上面這行代碼做了三件事:
- 分配了一個 int 類型的內存空間
- 初始化為 42
- 創建一個 shared_ptr
來管理這塊內存
也可以用構造函數直接綁定到已有的指針上,但這種方式要特別小心,容易出錯,不建議新手使用:
int* raw = new int(42); std::shared_ptr<int> ptr(raw); // 不推薦,除非你很清楚自己在做什么
使用 shared_ptr 時要注意什么?
-
不要混用裸指針和 shared_ptr
- 如果你已經用 shared_ptr 管理了一塊內存,就不要再用普通指針去操作它,否則可能造成重復釋放或者訪問已釋放內存。
-
循環引用問題
- 如果兩個對象各自持有對方的 shared_ptr,會導致引用計數永遠不為0,從而造成內存泄漏。這時候可以用 std::weak_ptr 來打破循環。
-
性能考慮
- shared_ptr 的引用計數操作是線程安全的,但也有一定開銷。如果你不需要共享所有權,優先使用 std::unique_ptr。
實際中怎么用?
常見的使用場景包括:
- 多個對象共享同一份資源,比如緩存、配置信息等
- 容器中保存動態分配的對象,避免手動釋放
- 回調函數中傳遞對象,防止對象提前被釋放
舉個例子:
#include <iostream> #include <memory> #include <vector> struct Data { int value; Data(int v) : value(v) { std::cout << "Constructedn"; } ~Data() { std::cout << "Destroyedn"; } }; int main() { std::vector<std::shared_ptr<Data>> vec; auto d = std::make_shared<Data>(10); vec.push_back(d); vec.push_back(d); std::cout << "Use count: " << d.use_count() << "n"; // 輸出 3 } // 離開作用域后,所有 shared_ptr 被銷毀,引用計數歸零,對象被釋放
在這個例子里,d 和 vec 中的兩個元素共同持有同一個 Data 對象,引用計數會變成3,當它們都離開作用域后才會釋放內存。
基本上就這些。掌握 shared_ptr 的基本用法和常見陷阱,就能在大多數項目中安全地使用它了。