亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解

P粉602998670
發(fā)布: 2025-08-16 18:29:01
原創(chuàng)
1044人瀏覽過

c++++中shared_ptr的循環(huán)引用問題會導(dǎo)致內(nèi)存泄漏,解決方法是使用weak_ptr。①循環(huán)引用發(fā)生在兩個或多個shared_ptr相互持有對方,引用計(jì)數(shù)無法歸零;②weak_ptr不增加引用計(jì)數(shù),僅用于臨時訪問對象,通過lock()獲取shared_ptr;③修改類定義,將其中一個shared_ptr改為weak_ptr即可打破循環(huán);④使用weak_ptr時應(yīng)注意不能直接操作對象、避免頻繁調(diào)用lock()、合理判斷是否需要強(qiáng)引用;⑤常見踩坑場景包括觀察者模式、樹形結(jié)構(gòu)回指和緩存系統(tǒng),應(yīng)優(yōu)先考慮是否需要強(qiáng)引用以避免不必要的依賴。

C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解

C++中,

shared_ptr
登錄后復(fù)制
的循環(huán)引用問題是個常見但容易忽視的陷阱。簡單來說,就是兩個或多個
shared_ptr
登錄后復(fù)制
互相持有對方,導(dǎo)致引用計(jì)數(shù)始終不為0,最終造成內(nèi)存泄漏。

C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解

解決辦法是使用

weak_ptr
登錄后復(fù)制
來打破這種循環(huán)。它不會增加對象的引用計(jì)數(shù),只是一個“弱引用”,可以用來觀察對象是否還活著,同時避免了強(qiáng)引用帶來的循環(huán)依賴。

C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解

為什么會出現(xiàn)循環(huán)引用?

最典型的場景就是兩個類之間相互持有

shared_ptr
登錄后復(fù)制

立即學(xué)習(xí)C++免費(fèi)學(xué)習(xí)筆記(深入)”;

class B; // 前向聲明

class A {
public:
    shared_ptr<B> ptr;
};

class B {
public:
    shared_ptr<A> ptr;
};
登錄后復(fù)制

如果創(chuàng)建兩個對象并讓它們互指:

C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解
auto a = make_shared<A>();
auto b = make_shared<B>();
a->ptr = b;
b->ptr = a;
登錄后復(fù)制

這時候,

a
登錄后復(fù)制
b
登錄后復(fù)制
的引用計(jì)數(shù)都是1(外部有一個),但因?yàn)楸舜艘渤钟幸粋€,所以即使外部不再使用,引用計(jì)數(shù)也不會變成0,無法釋放資源。


weak_ptr 是怎么解決這個問題的?

用一句話說:

weak_ptr
登錄后復(fù)制
不會影響引用計(jì)數(shù),只用于臨時訪問對象。

輕舟辦公
輕舟辦公

基于AI的智能辦公平臺

輕舟辦公194
查看詳情 輕舟辦公

修改上面的例子很簡單,把其中一個改為

weak_ptr
登錄后復(fù)制
即可:

class B; // 前向聲明

class A {
public:
    shared_ptr<B> ptr;
};

class B {
public:
    weak_ptr<A> ptr; // 改成 weak_ptr
};
登錄后復(fù)制

這樣,當(dāng)

a
登錄后復(fù)制
被釋放時,
b
登錄后復(fù)制
中的
ptr
登錄后復(fù)制
雖然還在,但它只是個“弱引用”,不會阻止
a
登錄后復(fù)制
被銷毀。之后如果想訪問這個對象,需要通過
lock()
登錄后復(fù)制
方法獲取一個臨時的
shared_ptr
登錄后復(fù)制

if (auto aPtr = b->ptr.lock()) {
    // aPtr 是一個有效的 shared_ptr,可以安全使用
} else {
    // 對象已經(jīng)被釋放
}
登錄后復(fù)制

使用 weak_ptr 的注意事項(xiàng)

  • 不能直接操作對象
    weak_ptr
    登錄后復(fù)制
    沒有
    operator->
    登錄后復(fù)制
    operator*
    登錄后復(fù)制
    ,必須先調(diào)用
    lock()
    登錄后復(fù)制
    轉(zhuǎn)成
    shared_ptr
    登錄后復(fù)制
  • 每次 lock() 都會產(chǎn)生一個新的 shared_ptr,所以要注意不要頻繁調(diào)用,否則可能影響性能
  • 不是萬能藥:如果邏輯本身就需要保持對象存活,那就不適合用
    weak_ptr
    登錄后復(fù)制
    ,得重新設(shè)計(jì)結(jié)構(gòu)

比如下面這段代碼就有點(diǎn)濫用:

for (int i = 0; i < 100000; ++i) {
    auto tmp = myWeakPtr.lock(); // 每次都 lock,效率低
    if (tmp) tmp->doSomething();
}
登錄后復(fù)制

應(yīng)該改成:

if (auto tmp = myWeakPtr.lock()) {
    for (int i = 0; i < 100000; ++i) {
        tmp->doSomething(); // 只 lock 一次
    }
}
登錄后復(fù)制

實(shí)際開發(fā)中哪些地方容易踩坑?

  • 觀察者模式:訂閱者保存的是
    shared_ptr
    登錄后復(fù)制
    ,發(fā)布者又反過來持有訂閱者,容易形成循環(huán)
  • 樹形結(jié)構(gòu):父子節(jié)點(diǎn)互相引用,父節(jié)點(diǎn)用
    shared_ptr
    登錄后復(fù)制
    ,子節(jié)點(diǎn)也應(yīng)該考慮用
    weak_ptr
    登錄后復(fù)制
    回指
  • 緩存系統(tǒng):緩存項(xiàng)持有對象的
    shared_ptr
    登錄后復(fù)制
    ,而其他模塊也可能有同樣的引用,如果不小心反過來引用緩存,就會出問題

遇到這些情況時,不妨多問一句:我這里真的需要一個強(qiáng)引用嗎?如果不是必須的,就該換成

weak_ptr
登錄后復(fù)制
。


基本上就這些。

weak_ptr
登錄后復(fù)制
不是什么高級技巧,但用得好可以避免很多隱藏的內(nèi)存泄漏問題。只要記住一點(diǎn):不需要控制生命周期的地方,就盡量別用
shared_ptr
登錄后復(fù)制
。

以上就是C++ shared_ptr循環(huán)引用怎么辦 weak_ptr解決方案詳解的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!

相關(guān)標(biāo)簽:
最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件

每個人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進(jìn)程會占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn
最新問題
開源免費(fèi)商場系統(tǒng)廣告
熱門教程
更多>
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長!
關(guān)注服務(wù)號 技術(shù)交流群
PHP中文網(wǎng)訂閱號
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號