欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中智能指針weak_ptr的原理及使用

 更新時(shí)間:2025年06月13日 10:11:11   作者:北辰alk  
weak_ptr是C++11引入的一種智能指針,本文主要介紹了C++中智能指針weak_ptr的原理及使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1. weak_ptr 的基本概念

weak_ptr 是 C++11 引入的一種智能指針,它與 shared_ptr 配合使用,主要解決以下問(wèn)題:

  • 打破循環(huán)引用:防止 shared_ptr 之間的循環(huán)引用導(dǎo)致內(nèi)存泄漏
  • 安全觀察:允許觀察共享對(duì)象而不影響其生命周期
  • 避免懸空指針:可以檢測(cè)被觀察對(duì)象是否已被釋放

2. weak_ptr 的核心原理

2.1 控制塊結(jié)構(gòu)

weak_ptr 與 shared_ptr 共享同一個(gè)控制塊,控制塊包含:

struct ControlBlock {
    std::atomic<size_t> shared_count;  // 強(qiáng)引用計(jì)數(shù)
    std::atomic<size_t> weak_count;    // 弱引用計(jì)數(shù)
    // 其他元數(shù)據(jù)(刪除器、分配器等)
};

2.2 內(nèi)存管理規(guī)則

  • 對(duì)象銷毀條件:當(dāng) shared_count 歸零時(shí),管理對(duì)象被銷毀
  • 控制塊銷毀條件:當(dāng) shared_count 和 weak_count 都?xì)w零時(shí),控制塊被釋放
  • weak_ptr 不參與所有權(quán):僅增加 weak_count,不影響 shared_count

2.3 工作流程

// 創(chuàng)建 shared_ptr(控制塊:shared=1, weak=0)
auto sp = std::make_shared<int>(42);

// 創(chuàng)建 weak_ptr(控制塊:shared=1, weak=1)
std::weak_ptr<int> wp = sp;

// shared_ptr 析構(gòu)(控制塊:shared=0, weak=1)
sp.reset();

// 此時(shí):
// - 管理的 int 對(duì)象已被銷毀
// - 控制塊仍然存在(weak_count=1)
// - wp.expired() == true

// weak_ptr 析構(gòu)(控制塊:shared=0, weak=0)
// 控制塊被釋放

3. weak_ptr 的關(guān)鍵操作

3.1 創(chuàng)建與賦值

// 從 shared_ptr 創(chuàng)建
auto sp = std::make_shared<MyClass>();
std::weak_ptr<MyClass> wp1(sp);

// 拷貝構(gòu)造
std::weak_ptr<MyClass> wp2(wp1);

// 賦值操作
std::weak_ptr<MyClass> wp3;
wp3 = wp1;

3.2 檢查與升級(jí)

// 檢查對(duì)象是否有效
if (!wp.expired()) {
    // 嘗試升級(jí)為 shared_ptr
    if (auto sp = wp.lock()) {
        // 使用 sp 安全訪問(wèn)對(duì)象
    }
}

3.3 資源釋放監(jiān)控

// 監(jiān)控資源釋放
std::weak_ptr<MyClass> wp;

{
    auto sp = std::make_shared<MyClass>();
    wp = sp;
    // 對(duì)象存在
}

// 此時(shí) wp.expired() == true

4. weak_ptr 的線程安全性

4.1 官方標(biāo)準(zhǔn)規(guī)定

  • 控制塊操作是原子的weak_count 的增減是線程安全的
  • lock() 操作是線程安全的:升級(jí)為 shared_ptr 的過(guò)程是原子的
  • 對(duì)象訪問(wèn)需要同步:通過(guò) lock() 獲取的 shared_ptr 需要額外同步

4.2 線程安全示例

std::shared_ptr<int> sp = std::make_shared<int>(42);
std::weak_ptr<int> wp(sp);

// 線程1
if (auto local_sp = wp.lock()) {
    std::lock_guard<std::mutex> lock(mtx);
    *local_sp = 10;
}

// 線程2
if (auto local_sp = wp.lock()) {
    std::lock_guard<std::mutex> lock(mtx);
    int val = *local_sp;
}

5. weak_ptr 的典型應(yīng)用場(chǎng)景

5.1 打破循環(huán)引用

class Parent {
    std::shared_ptr<Child> child;
};

class Child {
    std::weak_ptr<Parent> parent;  // 使用 weak_ptr 避免循環(huán)
};

5.2 緩存系統(tǒng)

class Cache {
    std::unordered_map<Key, std::weak_ptr<Resource>> cache;
    
    std::shared_ptr<Resource> get(Key key) {
        if (auto it = cache.find(key); it != cache.end()) {
            if (auto sp = it->second.lock()) {
                return sp;  // 緩存命中
            }
            cache.erase(it);  // 清理過(guò)期緩存
        }
        // 緩存未命中,創(chuàng)建新資源
        auto sp = std::make_shared<Resource>(key);
        cache[key] = sp;
        return sp;
    }
};

5.3 觀察者模式

class Subject {
    std::vector<std::weak_ptr<Observer>> observers;
    
    void notify() {
        for (auto it = observers.begin(); it != observers.end(); ) {
            if (auto obs = it->lock()) {
                obs->update();
                ++it;
            } else {
                it = observers.erase(it);  // 移除無(wú)效觀察者
            }
        }
    }
};

6. weak_ptr 的實(shí)現(xiàn)細(xì)節(jié)

6.1 控制塊生命周期

6.2 lock() 的原子實(shí)現(xiàn)

lock() 操作必須保證線程安全,偽代碼實(shí)現(xiàn):

shared_ptr<T> lock() const noexcept {
    ControlBlock* cb = get_control_block();
    size_t sc = cb->shared_count.load();
    do {
        if (sc == 0) return nullptr;  // 對(duì)象已釋放
        // 嘗試增加 shared_count(CAS操作)
    } while (!cb->shared_count.compare_exchange_weak(sc, sc + 1));
    
    return shared_ptr<T>(cb);  // 創(chuàng)建新的 shared_ptr
}

7. weak_ptr 的注意事項(xiàng)

不能直接解引用:必須先用 lock() 升級(jí)為 shared_ptr

// 錯(cuò)誤用法
// *wp;  // 編譯錯(cuò)誤

// 正確用法
if (auto sp = wp.lock()) {
    *sp = value;
}

性能考慮

  • lock() 操作包含原子操作,有一定開(kāi)銷
  • 控制塊需要額外內(nèi)存(通常16-32字節(jié))

構(gòu)造函數(shù)限制

// 不能直接從裸指針構(gòu)造
// std::weak_ptr<int> wp(new int(42));  // 錯(cuò)誤

// 必須從 shared_ptr 構(gòu)造
auto sp = std::make_shared<int>(42);
std::weak_ptr<int> wp(sp);  // 正確

8. 性能優(yōu)化建議

避免頻繁 lock/unlock:在需要時(shí)緩存 shared_ptr

void process(std::weak_ptr<Data> wp) {
    auto sp = wp.lock();  // 只調(diào)用一次 lock
    if (!sp) return;
    
    // 多次使用 sp 而不重復(fù)調(diào)用 lock
    sp->operation1();
    sp->operation2();
}

及時(shí)清理失效 weak_ptr:定期檢查并移除 expired() 的 weak_ptr

考慮使用 make_shared:對(duì)象和控制塊單次分配,減少內(nèi)存碎片

9. 與其它智能指針的對(duì)比

特性weak_ptrshared_ptrunique_ptr
所有權(quán)無(wú)共享獨(dú)占
影響生命周期
直接訪問(wèn)對(duì)象需通過(guò) lock()可直接訪問(wèn)可直接訪問(wèn)
引用計(jì)數(shù)只增加 weak_count增加 shared_count無(wú)
典型用途打破循環(huán)引用/觀察共享所有權(quán)獨(dú)占所有權(quán)

10. 現(xiàn)代 C++ 中的增強(qiáng)

10.1 C++17 的 weak_from_this

class MyClass : public std::enable_shared_from_this<MyClass> {
public:
    std::weak_ptr<MyClass> get_weak() {
        return weak_from_this();  // 安全獲取 weak_ptr
    }
};

auto obj = std::make_shared<MyClass>();
auto wobj = obj->get_weak();  // 安全獲取 weak_ptr

10.2 C++20 的原子 shared_ptr/weak_ptr

std::atomic<std::weak_ptr<int>> atomic_wp;
atomic_wp.store(wp, std::memory_order_release);
auto current = atomic_wp.load(std::memory_order_acquire);

11. 總結(jié)

weak_ptr 的核心原理可以總結(jié)為:

  • 不參與所有權(quán):僅觀察不擁有,不影響對(duì)象生命周期
  • 共享控制塊:與 shared_ptr 共享同一控制塊,維護(hù) weak_count
  • 安全升級(jí):通過(guò) lock() 原子操作獲取可用的 shared_ptr
  • 自動(dòng)清理:當(dāng)最后一個(gè) weak_ptr 析構(gòu)后,控制塊被釋放

正確使用 weak_ptr 可以:

  • 有效解決循環(huán)引用導(dǎo)致的內(nèi)存泄漏
  • 實(shí)現(xiàn)安全的對(duì)象觀察模式
  • 構(gòu)建高效的緩存系統(tǒng)
  • 開(kāi)發(fā)更健壯的異步代碼

理解 weak_ptr 的工作原理對(duì)于設(shè)計(jì)復(fù)雜的內(nèi)存管理系統(tǒng)和避免資源泄漏至關(guān)重要,它是現(xiàn)代 C++ 高效內(nèi)存管理工具鏈中不可或缺的一環(huán)。

到此這篇關(guān)于C++中智能指針weak_ptr的原理及使用的文章就介紹到這了,更多相關(guān)C++ weak_ptr內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論