C++基礎(chǔ)(九)-shared_ptr,weak_ptr與unique_ptr

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)存泄漏,使代碼更安全清晰。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容