網(wǎng)站到期怎么續(xù)費網(wǎng)上商城推廣13種方法
弱引用智能指針 std::weak_ptr 可以看做是shared_ptr的助手,它不管理 shared_ptr 內(nèi)部的指針。std::weak_ptr 沒有重載操作符*和->,因為它不共享指針,
不能操作資源,所以它的構(gòu)造不會增加引用計數(shù),析構(gòu)也不會減少引用計數(shù),它的主要作用就是作為一個旁觀者監(jiān)視shared_ptr 中管理的資源是否存在.
初始化
#include<iostream>
#include<memory>
using namespace std;int main(){shared_ptr<int> sp(new int);//weak_ptr<int> wp1;//空weak_ptr對象weak_ptr<int> wp2(wp1);//也是空weak_ptr<int> wp3(sp);//通過shared_ptr對象構(gòu)造一個可用的weak_ptr實例對象,就是wp3監(jiān)管spweak_ptr<int> wp4;wp4=sp;//通過shared_ptr對象構(gòu)造一個可用的weak_ptr實例對象(這是一個隱式類型轉(zhuǎn)換),給賦值運算符重載了weak_ptr<int> wp5;wp5=wp3;//通過weak_ptr對象構(gòu)造一個可用的weak_ptr實例對象,給賦值運算符重載了
}
use_count()
通過調(diào)用weak_ptr類提供的use_count()方法可以獲得當前觀測資源的引用計數(shù)
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp(new int);
weak_ptr<int> wp1;
weak_ptr<int> wp2(wp1);
weak_ptr<int> wp3(sp);
weak_ptr<int> wp4;
wp4 = sp;
weak_ptr<int> wp5;
wp5 = wp3;
cout << wp1.use_count() << endl;
cout << wp2.use_count() << endl;
cout << wp3.use_count() << endl;
cout << wp4.use_count() << endl;
cout << wp5.use_count() << endl;
}/*運行結(jié)果:
0
0
1
1
1*/
通過打印的結(jié)果可以知道,雖然弱引用智能指針 wp3、wp4、wp5 監(jiān)測的資源是同一個,但是它的引用計數(shù)并沒有發(fā)生任何的變化,也進一步證明了 weak_ptr 只是監(jiān)測資源,并不管理資源。
expired()(失效的)
通過調(diào)用 std::weak_ptr 類提供的 expired()方法來判斷觀測的資源是否已經(jīng)被釋放
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> shared(new int(10));
weak_ptr<int> weak(shared);
cout << weak.expired() << endl;
shared.reset();
cout << weak.expired() << endl;return 0;
}
/*運行結(jié)果:
0
1*/
weak_ptr監(jiān)測的就是shared_ptr管理的資源,當共享智能指針調(diào)用 shared.reset();之后管理的資源被釋放,因此 weak.expired()函數(shù)的結(jié)果返回 true,表示監(jiān)測的資源已經(jīng)不存在了。
lock()
通過調(diào)用weak_ptr類提供的lock()方法來獲取管理所監(jiān)測資源的shared_ptr對象
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp1, sp2;
weak_ptr<int> wp;
sp1 = make_shared<int>(520);
wp = sp1;
sp2 = wp.lock();
cout << wp.use_count() << endl;
sp1.reset();
cout << wp.use_count() << endl;
sp1 = wp.lock();
cout << wp.use_count() << endl;cout << *sp1 << endl;
cout << *sp2 << endl;return 0;
}/*運行結(jié)果:
2
1
2
520
520*/
sp2 = wp.lock();通過調(diào)用 lock()方法得到一個用于管理 weak_ptr 對象所監(jiān)測的資源的共享智能指針對象,使用這個對象初始化 sp2,此時所監(jiān)測資源的引用計數(shù)為 2.
sp1.reset();共亨智能指針 sp1 被重置,weak_ptr 對象所監(jiān)測的資源的引用計數(shù)減 1
sp1 = wp.lock();sp1 重新被初始化,并且管理的還是 weak_ptr 對象所監(jiān)測的資源,因此引用計數(shù)加 1.
共享智能指針對象 sp1 和 sp2 管理的是同一塊內(nèi)存,因此最終打印的內(nèi)存中的結(jié)果是相同的,都是 520.
reset()
通過調(diào)用 std::weak_ptr 類提供的 reset()方法來清空對象,使其不監(jiān)測任何資源。
#include<iostream>
#include<memory>
using namespace std;
int main() {
shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
cout << wp.expired() << endl;
wp.reset();
cout << wp.expired() << endl;
cout << sp.use_count() << endl;return 0;
}/*運行結(jié)果:
0
1
1*/
返回管理this的shared_ptr
#include<iostream>
#include<memory>
using namespace std;struct Test
{shared_ptr<Test> getSharedPtr(){return shared_ptr<Test>(this); }~Test(){cout<<"析構(gòu)函數(shù)"<<endl; }
};
int main()
{shared_ptr<Test> sp1(new Test);cout<<"引用個數(shù)"<<sp1.use_count()<<endl;shared_ptr<Test> sp2=sp1->getSharedPtr();cout<<"引用個數(shù)"<<sp1.use_count()<<endl;return 0;
}
當用Test的對象初始化sp1時,sp1指向這個對象,當sp1調(diào)用getSharedPtr函數(shù)時,要給隱含參數(shù)this傳值,傳的就是Test對象的原始地址,這就會導致用原始地址初始化多次智能指針,這倆智能指針各自維護著自己的引用計數(shù),當一個引用計數(shù)為0時,就會釋放那塊空間,而另一個指針不知道那塊空間被釋放,會再次釋放那塊空間,導致二次釋放問題
通過輸出的結(jié)果可以看到一個對象被析構(gòu)了兩次,其原因是這樣的:在這個例子中使用同一個指針 this 構(gòu)造了兩個智能指針對象 sp1 和 sp2,這二者之間是沒有任何關(guān)系的,因為 sp2 并不是通過 sp1 初始化得到的實例對象。在離開作用域之后 this 將被構(gòu)造的兩個智能指針各自析構(gòu)導致重復析構(gòu)的錯誤。
循環(huán)引用
#include<iostream>
#include<memory>
using namespace std;class A;
class B;
class A{
public:shared_ptr<B> bptr;~A(){cout<<"A的析構(gòu)"<<endl; }
};
class B{
public:shared_ptr<A> aptr;~B(){cout<<"B的析構(gòu)"<<endl; }
};
void testPtr(){shared_ptr<A> ap(new A);shared_ptr<B> bp(new B);cout<<"A的引用計數(shù):"<<ap.use_count()<<endl;cout<<"B的引用計數(shù):"<<bp.use_count()<<endl;ap->bptr=bp;bp->aptr=ap;cout<<"A的引用計數(shù):"<<ap.use_count()<<endl;cout<<"B的引用計數(shù):"<<bp.use_count()<<endl;
}
int main(){testPtr();return 0;
}
當作用域結(jié)束,想要釋放A對象,就得讓A對象里面的bptr引用計數(shù)為0,但是aptr指向的是B,只有B沒有,bptr引用計數(shù)才為0,但是B里有個aptr,只有aptr引用計數(shù)為0,B才能沒,但是aptr指向的是A,只有A沒了,aptr才能沒,這就導致,兩邊都沒不了,ap和bp引用計數(shù)都不為0
要解決這個循環(huán)引用問題,可以考慮使用weak_ptr(弱指針)來打破循環(huán)引用,例如將類A中的shared_ptr改為weak_ptr,類B中的shared_ptr改為weak_ptr,這樣就可以在需要訪問對方對象時通過weak_ptr的lock方法來獲取有效的shared_ptr,同時又不會造成循環(huán)引用導致的析構(gòu)函數(shù)無法調(diào)用的問題。