智能指針std::weak_ptr


std::weak_ptr

避免shared_ptr內存泄漏的利器。👈


smart pointer 三兄弟性格各異。unque_ptr是獨來獨往,shared_ptr是左擁右抱,而weak_ptr生來就不是為了單打獨斗,了解之后你會發現他總是和shared_ptr出雙入對。

既然shared_ptr是智能指針,那理所應當不會發生內存泄漏,那么為什么👆還會說“避免shared_ptr內存泄漏”呢?我們不禁疑惑👇

shared_ptr怎么導致的內存泄漏?

我們知道shared_ptr的特性是:內含一個計數器(可能是計數器,也可能其他數據結構),掌握着share某對象的指針的數量(shared_ptr.use_count()可知),當計數器值為0時,它壽終正寢連帶它的對象也一起陪葬(被它的析構函數銷毀),好不霸道。但就是這么強勢的它,也有翻船(發生內存泄漏)的時候---循環引用

看👇的例子

 1 #include <iostream>
 2 #include <memory>
 3 using namespace std;
 4 
 5 class B;
 6 class A
 7 {
 8 public:
 9     A() { cout << "A's constructor ..." << endl; }
10     ~A() { cout << "A's destructor ..." << endl; }
11     
12     std::shared_ptr<B> b;//class A中含有指向class B的shared指針
13 };
14 
15 class B
16 {
17 public:
18     B() { cout << "B's constructor ..." << endl; }
19     ~B() { cout << "B's destructor ..." << endl; }
20 
21     std::shared_ptr<A> a; //class B 中含有指向class A的shared指針
22 };
23 
25 int main() 
26 {
27     std::shared_ptr<A> aa = make_shared<A>(); //aa->object A  aa計數器 1
28     std::shared_ptr<B> bb = make_shared<B>(); //bb->object B  bb計數器 1
29 
30     aa->b = bb;// aa 計數器來到了 2 31     bb->a = aa;// bb 計數器來到了 2 32 
33     return 0;
34 }

class A中含有指向class B的shared指針, class B 中含有指向class A的shared指針,這樣形成了循環引用。
我們來看輸出結果👇

可以看到,兩個類對象都進行了構造,卻沒有析構銷毀掉,發生了內存泄漏⚡⚡

為什么呢?其實,在執行完一下語句后,shared_ptr計數器就加到了2,而出了main函數作用域,其計數會-1,成為 1,不為0,所以該對象未被析構(銷毀)。

aa->b = bb;// aa 計數器來到了 2
bb->a = aa;// bb 計數器來到了 2

這可如何是好,連智能指針都出現內存泄露了,我還是回去用我的一般指針?當然不是!

❇❇weak_ptr閃亮登場❇❇

weak_ptr為什么存在?

特性:

不可使用* 和 ->訪問對象

被賦值,不會引起shared_ptr內部計數器值變化(我猜是它嚴格上來說不具備指針的能力---訪問對象)

 所以,我們就可以用weak_ptr替代shared_ptr, 看👇例子。

 1 #include <iostream>
 2 #include <memory>
 3 using namespace std;
 4 
 5 class B;
 6 class A
 7 {
 8 public:
 9     A() { cout << "A's constructor ..." << endl; }
10     ~A() { cout << "A's destructor ..." << endl; }
11     
12     std::weak_ptr<B> weak_b; 13 };
14 
15 class B
16 {
17 public:
18     B() { cout << "B's constructor ..." << endl; }
19     ~B() { cout << "B's destructor ..." << endl; }
20 
21     std::weak_ptr<A> weak_a; 22 };
23 
25 int main() 
26 {
27     std::shared_ptr<A> aa = make_shared<A>(); //aa->object A aa計數器 1
28     std::shared_ptr<B> bb = make_shared<B>(); //bb->object B bb計數器 1
29 
30     aa->weak_b = bb; //計數器還是1哦 31     bb->weak_a = aa; //計數器還是1哦 32 
33     return 0;
34 }

再來看下結果👇

object A & B都被成功析構(銷毀)了。那么循環引用導致shared_ptr發生內存泄漏的問題迎刃而解!

原因是:weak_ptr不會增加shared_ptr的計數器,從而離開mian函數作用域時,shared_ptr aa & bb 計數器都 -1 ,成為0, 具備銷毀條件,調用析構函數銷毀自己和所指對象

至此,我們終於可以說weak_ptr具備避免內存泄漏的功能了!!!


 

 參考:https://www.cnblogs.com/DswCnblog/p/5628314.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM