1.定義
- shared_ptr 和 unique_ptr 是 C++11 引入的智能指針,用于自動(dòng)管理動(dòng)態(tài)內(nèi)存,防止內(nèi)存泄漏。它們的主要區(qū)別在于所有權(quán)語義。
2.使用
2.1 unique_ptr(獨(dú)占指針)
2.1.1 簡單使用
#include <memory>
// 創(chuàng)建獨(dú)占指針
std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
// 錯(cuò)誤:不能復(fù)制
// std::unique_ptr<int> ptr2 = ptr1;
// 可以移動(dòng)所有權(quán)
std::unique_ptr<int> ptr2 = std::move(ptr1); // ptr1 現(xiàn)在為 nullptr
// 自定義刪除器
auto deleter = [](int* p) { delete p; std::cout << "deleted\n"; };
std::unique_ptr<int, decltype(deleter)> ptr3(new int(10), deleter);
2.1.2 特點(diǎn)
- 獨(dú)占資源所有權(quán)
- 離開作用域時(shí)自動(dòng)釋放內(nèi)存
- 支持?jǐn)?shù)組版本:unique_ptr<T[]>
- 可以自定義刪除器
2.2 shared_ptr(共享指針)
#include <memory>
// 創(chuàng)建共享指針(推薦使用 make_shared)
std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
// 可以復(fù)制,引用計(jì)數(shù)增加
std::shared_ptr<int> ptr2 = ptr1; // 引用計(jì)數(shù): 2
std::shared_ptr<int> ptr3 = ptr2; // 引用計(jì)數(shù): 3
// 一個(gè)指針離開作用域
{
std::shared_ptr<int> ptr4 = ptr3; // 引用計(jì)數(shù): 4
} // ptr4 銷毀,引用計(jì)數(shù): 3
// 自定義刪除器
std::shared_ptr<int> ptr4(new int(100), [](int* p) {
delete p;
std::cout << "custom delete\n";
});
2.2 shared_ptr與weak_ptr(共享指針)
- 不會(huì)增加引用計(jì)數(shù)
#include <memory>
std::shared_ptr<int> sp = std::make_shared<int>(42);
// 創(chuàng)建 weak_ptr
std::weak_ptr<int> wp1 = sp; // 從 shared_ptr 構(gòu)造
std::weak_ptr<int> wp2;
// 賦值操作
wp2 = wp1; // ? 允許:weak_ptr 之間賦值
wp2 = sp; // ? 允許:從 shared_ptr 賦值
// wp2 = std::make_shared<int>(10); // ? 也可以
std::cout << "sp.use_count() = " << sp.use_count() << std::endl; // 輸出: 1
// weak_ptr 賦值不會(huì)增加引用計(jì)數(shù)!
- weak_ptr 的關(guān)鍵方法
lock() - 安全獲取 shared_ptr
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
std::weak_ptr<int> wp = sp;
// 方法1:檢查后再打印
std::shared_ptr<int> locked = wp.lock();
if (locked) {
std::cout << "wp指向的值: " << *locked << std::endl;
std::cout << "引用計(jì)數(shù): " << locked.use_count() << std::endl; // 輸出: 2
} else {
std::cout << "對象已銷毀" << std::endl;
}
// 方法2:使用臨時(shí)變量(推薦)
if (auto sp2 = wp.lock()) {
std::cout << "值: " << *sp2 << std::endl;
}
return 0;
}
2.2.1 注意
- weak_ptr 是一個(gè)觀察者。本身不存儲(chǔ)值,只存儲(chǔ)一個(gè)指向控制塊的指針
- 必須先 lock() 獲取 shared_ptr 才能訪問值
- lock() 會(huì)增加引用計(jì)數(shù)(臨時(shí)增加)-
- 如果對象已銷毀,lock() 返回空的 shared_ptr
2.3 選擇指南
- 默認(rèn)使用 unique_ptr - 除非需要共享所有權(quán)
- 優(yōu)先使用 make_unique/make_shared - 異常安全且高效
- 使用 shared_ptr 時(shí)注意循環(huán)引用 - 必要時(shí)使用 weak_ptr
- 避免裸指針與智能指針混用
- 不要使用 shared_ptr 管理數(shù)組 - 用 unique_ptr<T[]> 或 vector
總結(jié)
- unique_ptr: "這個(gè)資源只屬于我,我負(fù)責(zé)釋放"
- shared_ptr: "這個(gè)資源我們可以共享,最后一個(gè)使用者負(fù)責(zé)釋放"
- 根據(jù)所有權(quán)的需求選擇合適的智能指針,能有效避免內(nèi)存泄漏,使代碼更安全清晰。