C++標(biāo)準(zhǔn)庫學(xué)習(xí)之weak_ptr智能指針用法詳解
在上一篇文章中介紹了 shared_ptr 這種智能指針,他為了解決在指針沒有引用的情況下自動回收資源這種情況而產(chǎn)生的,但是在部分情況下會產(chǎn)生另一種問題,那就是兩個智能指針被循環(huán)引用 , a 使用 shared_ptr 引用了b ,同時 b 使用 shared_ptr 引用了 a,在 方法執(zhí)行完成后 ,a 與 b 的智能指針都會被 釋放,但是 由于他們互相持有 , a 與 b 的 used_count >0 ,那么就不會釋放他們的資源,看下面的例子
#include <iostream> #include <memory> #include <vector> using namespace std; class Person{ public: // 構(gòu)造方法 ,name 是必要參數(shù) mum 與 dad 是非必要參數(shù) Person(string name,shared_ptr<Person> mum = nullptr ,shared_ptr<Person> dad = nullptr) :name(name) ,mum(mum),dad(dad)// 此種初始化方式被經(jīng)常應(yīng)用到 jni 源碼上 { } // 析構(gòu)函數(shù),資源被釋放時會被調(diào)用 ~Person(){ cout<<"對象名稱是->" << name<< "被回收了"<<endl; } // 向量 vector<shared_ptr<Person>> child; //名字 string name; // 智能指針引用mum shared_ptr<Person> mum; //智能指針引用dad shared_ptr<Person> dad; }; // 初始化 家人,讓他們循環(huán)引用 shared_ptr<Person> getFamily(const string& name){ shared_ptr<Person> mum(new Person(name +"'s Mum")); shared_ptr<Person> dad(new Person(name +"'s Dad")); shared_ptr<Person> child(new Person(name,mum,dad)); mum->child.push_back(child); dad->child.push_back(child); return child; } int main(){ shared_ptr<Person> tsm= getFamily("tsm"); cout<< "------------before change-----------"<<endl; cout << tsm->dad->name<<endl; cout << tsm->mum->name<<endl; cout << tsm->name<<endl; cout<<"tsm 的引用個數(shù)" <<tsm.use_count()<<endl; cout<< "------------start change-----------"<<endl; tsm = getFamily("tsm1"); cout<< "------------after change-----------"<<endl; system("pause"); return 0; }
結(jié)果:
D:\CWorkSpace\tsmTest\cmake-build-debug\tsmTest.exe
------------before change-----------
tsm's Dad
tsm's Mum
tsm
tsm 的引用個數(shù)3
------------start change-----------
------------after change-----------
. . . pause . . .
發(fā)現(xiàn)在為 tsm 這個變量二次賦值時,第一次 shared_ptr 指針指向的資源內(nèi)存應(yīng)該是被釋放的,但是他們的析構(gòu)函數(shù)并沒有被執(zhí)行,那就證明他的資源并沒有被釋放,那么我們?nèi)绾蝸硇薷膬?nèi),這就引出了我們今天的主角 weak_ptr
修改如下
class Person{ public: // 構(gòu)造方法 ,name 是必要參數(shù) mum 與 dad 是非必要參數(shù) Person(string name,shared_ptr<Person> mum = nullptr ,shared_ptr<Person> dad = nullptr) :name(name) ,mum(mum),dad(dad)// 此種初始化方式被經(jīng)常應(yīng)用到 jni 源碼上 { } // 析構(gòu)函數(shù),資源被釋放時會被調(diào)用 ~Person(){ cout<<"對象名稱是->" << name<< "被回收了"<<endl; } // 將向量中的引用使用 weak_ptr ,打破互相引用即可 vector<weak_ptr<Person>> child; //名字 string name; // 智能指針引用mum shared_ptr<Person> mum; //智能指針引用dad shared_ptr<Person> dad; };
修改后的結(jié)果如下:
------------before change-----------
tsm's Dad
tsm's Mum
tsm
tsm 的引用個數(shù)1
------------start change-----------
對象名稱是->tsm被回收了
對象名稱是->tsm's Dad被回收了
對象名稱是->tsm's Mum被回收了
------------after change-----------
發(fā)現(xiàn)在使用 weak_ptr 打破互相引用的后, 被覆蓋的 tsm 的析構(gòu)函數(shù)被成功調(diào)用了,
weak_ptr 的使用場景主要有2個
1: 打破 shared_ptr 使用混亂出現(xiàn)的情況導(dǎo)致循環(huán)引用的情況,
2: 如果持有該 shared_ptr 的對象的生命周期是大于 該 shared_ptr 指針的生命周期的情況,就會導(dǎo)致 shared_ptr 資源無法被回收,
weak_ptr 的創(chuàng)建方式有3中
1:
weak_ptr<Person> t0; //構(gòu)造空對象
2:
weak_ptr<Person> t1(t0); //使用拷貝構(gòu)造函數(shù)
3:
shared_ptr<Person> tsm= getFamily("tsm"); weak_ptr<Person> t2(tsm);
檢查weak_ptr 是否還有效
t2.expired()
expired 源碼如下
bool expired() const noexcept { return _M_refcount._M_get_use_count() == 0; }
可以看到 返回的是 use_count ,那就證明 if(!t2.expired) 則證明他是有效的
使用 weak_ptr,使用lock 方法將 weak_ptr 轉(zhuǎn)換成 shared_ptr ,防止在使用過程中資源被回收
shared_ptr<Person> tt = t2.lock();
看一下lock 的源碼
shared_ptr<_Tp> lock() const noexcept { return shared_ptr<_Tp>(*this, std::nothrow); }
到此這篇關(guān)于C++標(biāo)準(zhǔn)庫學(xué)習(xí)之weak_ptr智能指針用法詳解的文章就介紹到這了,更多相關(guān)C++ weak_ptr智能指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
排列和組合算法的實(shí)現(xiàn)方法_C語言經(jīng)典案例
下面小編就為大家?guī)硪黄帕泻徒M合算法的實(shí)現(xiàn)方法_C語言經(jīng)典案例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09C++實(shí)現(xiàn)LeetCode(67.二進(jìn)制數(shù)相加)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(67.二進(jìn)制數(shù)相加),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語言指針變量作為函數(shù)參數(shù)的實(shí)現(xiàn)步驟詳解
這篇文章主要介紹了C語言指針變量作為函數(shù)參數(shù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02