auto_ptr (C++98):**已棄用 (C++11)**,移動語義缺陷導致所有權轉移隱患unique_ptr (C++11):**獨占所有權**,零開銷,支持數組shared_ptr (C++11):**共享所有權**,引用計數,線程安全控制塊weak_ptr (C++11):**非擁有觀察者**,打破循環引用std::unique_ptr<int> p1(new int(42));
std::unique_ptr<int> p2 = std::move(p1); // 显式移動,p1 置空
// p2 = p1; // 編譯錯誤:禁止拷貝
// 數組專用版本
std::unique_ptr<int[]> arr(new int[10]);
arr[5] = 100; // 支持下標訪問
// 自定義刪除器
auto deleter = [](FILE* f){ fclose(f); };
std::unique_ptr<FILE, decltype(deleter)> fp(fopen("a.txt","r"), deleter);
關鍵特性:移動構造/賦值轉移所有權;臨時對象賦值合法(右值引用);無額外控制塊開銷,大小等同裸指針。
堆上分配控制塊,包含:
std::shared_ptr<int> sp1 = std::make_shared<int>(42); // 推薦:單次分配對象+控制塊 std::shared_ptr<int> sp2 = sp1; // 引用計數 +1 sp1.use_count(); // 2 sp1.reset(); // 計數 -1,sp2 仍持有 // 計數歸零時調用刪除器釋放對象
shared_ptr() noexcept; template<class Y> explicit shared_ptr(Y* p); template<class Y, class D> shared_ptr(Y* p, D d); shared_ptr(const shared_ptr& r) noexcept; shared_ptr& operator=(const shared_ptr& r) noexcept; void reset(); T& operator*() const; T* operator->() const; T* get() const; bool unique() const; // use_count() == 1 long use_count() const; explicit operator bool() const; // 可用於 if(sp) void swap(shared_ptr& other);
不增加強引用計數**,僅增加弱引用計數。對象銷毀時弱引用計數不為 0,控制塊保留直到最後 weak_ptr 銷毀。
std::shared_ptr<Node> parent = std::make_shared<Node>();
std::shared_ptr<Node> child = std::make_shared<Node>();
parent->child = child;
child->parent = std::weak_ptr<Node>(parent); // 父指針用 weak_ptr
// 使用時鎖定
if (auto p = child->parent.lock()) {
// p 是 shared_ptr,安全訪問
}
lock() 原子檢查強計數>0 並構造 shared_ptr,失敗返回空。
| 場景 | 推薦 | 理由 |
|---|---|---|
| 單一所有者、作用域內管理 | unique_ptr | 零開銷、編譯期強制所有權轉移 |
| 多所有者、生命周期不確定 | shared_ptr | 引用計數自動管理 |
| 觀察者/緩存/父子雙向引用 | weak_ptr | 不延長生命周期、打破循環 |
| STL 容器存儲指針 | shared_ptr | 支持拷貝/賦值,算法兼容 |
| 工廠函數返回 | unique_ptr | 明確所有權轉移給調用者 |
make_unique (C++14) / make_shared