首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++11 智能指針 weak_ptr 使用場景與循環引用解決方案

     編輯:關於C++

std::weak_ptr 是 C++11 引入的弱引用智能指針,不佔有對象所有權,不增加引用計數。主要用於打破 shared_ptr 循環引用及緩存/觀察者模式中臨時訪問對象。

一、核心特性

  • 不擁有對象,構造/拷貝不增加引用計數。
  • 必須調用 lock() 生成 shared_ptr 才能訪問對象;若對象已銷毀,lock() 返回空指針。
  • expired() 判斷對象是否仍存活。
  • 可由 shared_ptr 隱式構造,也可 reset() 置空。

二、經典場景:打破循環引用

問題:Man 持有 shared_ptr,Woman 持有 shared_ptr,引用計數永遠 ≥ 2,析構函數永不調用 → 內存洩漏。

解決:一方改用 weak_ptr:

#include <memory>
#include <iostream>

struct Woman; // 前向宣告

struct Man {
    std::shared_ptr wife; // 強引用
    ~Man() { std::cout << "Man dtor\n"; }
};

struct Woman {
    std::weak_ptr husband; // 弱引用,不增加計數
    ~Woman() { std::cout << "Woman dtor\n"; }
};

int main() {
    auto man = std::make_shared();
    auto woman = std::make_shared();
    man->wife = woman;
    woman->husband = man; // 不構成循環
    // 離開作用域時 man、woman 計數歸 0,正常析構
}

三、場景二:緩存/觀察者——延遲鎖定

線程 A 為主邏輯,B/C 為可選輔助任務。B/C 持有 weak_ptr 觀察 A 的資源:

std::weak_ptr gw;

void worker() {
    if (auto sp = gw.lock()) { // 臨時升級為強引用
        sp->doSomething();
    } else {
        std::cout << "Resource already released\n";
    }
}

void testScope() {
    auto sp = std::make_shared();
    gw = sp;
    worker(); // 正常訪問
    sp.reset(); // 主邏輯釋放
    worker(); // 提示已釋放
}

四、代碼範例輸出解析

TestWeakPtrScope_1
42          // lock 成功,對象存活
42          // sp1 持有 strong ref,對象仍存活
TestWeakPtrScope_2
42          // lock 成功
gw is expired // 離開作用域後 sp 銷毀,gw.expired() 為真

五、最佳實踐建議

  1. 父持有子用 shared_ptr,子指向父用 weak_ptr(樹形結構通用原則)。
  2. 緩存系統中,緩存條目持有 weak_ptr,定期掃描 expired() 清理失效項。
  3. 多線程環境下,lock() 返回的 shared_ptr 保證線程安全(引用計數原子操作)。
  4. 不要濫用 weak_ptr 替代裸指針;只有在「可能需要訪問、但不應延長生命週期」時才使用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved