中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

公司做網(wǎng)站合肥網(wǎng)站制作推廣

公司做網(wǎng)站,合肥網(wǎng)站制作推廣,wordpress增加面包屑導(dǎo)航,怎么做網(wǎng)站301重定向智能指針 shared_ptrshared_ptr的基本用法使用shared_ptr要注意的問(wèn)題 unique_ptr獨(dú)占的智能指針weak_ptr弱引用的智能指針weak_ptr的基本用法weak_ptr返回this指針weak_ptr解決循環(huán)引用問(wèn)題 weak_ptr使用注意事項(xiàng) 智能指針 C程序設(shè)計(jì)中使用堆內(nèi)存是非常頻繁的操作&#xff0…

智能指針 shared_ptrshared_ptr的基本用法使用shared_ptr要注意的問(wèn)題 unique_ptr獨(dú)占的智能指針weak_ptr弱引用的智能指針weak_ptr的基本用法weak_ptr返回this指針weak_ptr解決循環(huán)引用問(wèn)題 weak_ptr使用注意事項(xiàng)

智能指針

C++程序設(shè)計(jì)中使用堆內(nèi)存是非常頻繁的操作,堆內(nèi)存的申請(qǐng)和釋放都由程序員自己管理。程序員自己 管理堆內(nèi)存可以提高了程序的效率,但是整體來(lái)說(shuō)堆內(nèi)存的管理是麻煩的,C++11中引入了智能指針的 概念,方便管理堆內(nèi)存。使用普通指針,容易造成堆內(nèi)存泄露(忘記釋放),二次釋放,程序發(fā)生異常 時(shí)內(nèi)存泄露等問(wèn)題等,使用智能指針能更好的管理堆內(nèi)存。

C++里面的四個(gè)智能指針: auto_ptr,unique_ptr,shared_ptr, weak_ptr 其中后三個(gè)是C++11支持, 并且第一個(gè)已經(jīng)被C++11棄用。

shared_ptr

共享的智能指針 std::shared_ptr使用引用計(jì)數(shù),每一個(gè)shared_ptr的拷貝都指向相同的內(nèi)存。再最后一個(gè)shared_ptr析 構(gòu)的時(shí)候,內(nèi)存才會(huì)被釋放。 shared_ptr共享被管理對(duì)象,同一時(shí)刻可以有多個(gè)shared_ptr擁有對(duì)象的所有權(quán),當(dāng)最后一個(gè) shared_ptr對(duì)象銷毀時(shí),被管理對(duì)象自動(dòng)銷毀。 簡(jiǎn)單來(lái)說(shuō),shared_ptr實(shí)現(xiàn)包含了兩部分,

  • 一個(gè)指向堆上創(chuàng)建的對(duì)象的裸指針:raw_ptr

  • 一個(gè)指向內(nèi)部隱藏的、共享的管理對(duì)象:share_count_object

第一部分沒什么好說(shuō)的,第二部分是需要關(guān)注的重點(diǎn). use_count:當(dāng)前這個(gè)堆上對(duì)象被多少對(duì)象引用了,簡(jiǎn)單來(lái)說(shuō)就是引用計(jì)數(shù)。

shared_ptr的基本用法

  1. 初始化

通過(guò)構(gòu)造函數(shù)、std::shared_ptr輔助函數(shù)和reset方法來(lái)初始化shared_ptr,代碼如下:

// 智能指針初始化std::shared_ptr<int> p1(new int(1));std::shared_ptr<int> p2 = p1;std::shared_ptr<int> p3;p3.reset(new int(1));if(p3) {cout << "p3 is not null";}

我們應(yīng)該優(yōu)先使用make_shared來(lái)構(gòu)造智能指針,因?yàn)樗咝А?/strong>

auto sp1 = make_shared<int>(100);//相當(dāng)于shared_ptr<int> sp1(new int(100));

不能將一個(gè)原始指針直接賦值給一個(gè)智能指針,例如,下面這種方法是錯(cuò)誤的:

std::shared_ptr<int> p = new int(1);

shared_ptr不能通過(guò)“直接將原始這種賦值”來(lái)初始化,需要通過(guò)構(gòu)造函數(shù)和輔助方法來(lái)初始化。 對(duì)于一個(gè)未初始化的智能指針,可以通過(guò)reset方法來(lái)初始化,當(dāng)智能指針有值的時(shí)候調(diào)用reset會(huì)引起 引用計(jì)數(shù)減1。另外智能指針通過(guò)重載的bool類型操作符來(lái)判斷是否為空。

#include <iostream>#include <memory>using namespace std;void test(shared_ptr<int> sp) {// sp在test里面的作用域cout << "test sp.use_count()" <<sp.use_count() << endl;}int main(){auto sp1 = make_shared<int>(100); // 優(yōu)先使用make_shared來(lái)構(gòu)造智能指針//相當(dāng)于shared_ptr<int> sp2(new int(100));// ?  std::shared_ptr<int> p = new int(1);  // 不能將一個(gè)原始指針直接賦值給一個(gè)智能指針std::shared_ptr<int> p1;p1.reset(new int(1)); ?// 有參數(shù)就是分配資源std::shared_ptr<int> p2 = p1;// 引用計(jì)數(shù)此時(shí)應(yīng)該是2cout << "p2.use_count() = " << p2.use_count()<< endl; ?// 2cout << "p1.use_count() = " << p1.use_count()<< endl; ?// 2p1.reset(); ? // 沒有參數(shù)就是釋放資源cout << "p1.reset()\n";// 引用計(jì)數(shù)此時(shí)應(yīng)該是1cout << "p2.use_count()= " << p2.use_count() << endl; ?// 1cout << "p1.use_count() = " << p1.use_count()<< endl; ?// 2if(!p1) { ?// p1是空的cout << "p1 is empty\n";}if(p2) { // p2非空cout << "p2 is not empty\n";}p2.reset();cout << "p2.reset()\n";cout << "p2.use_count()= " << p2.use_count() << endl;if(!p2) {cout << "p2 is empty\n";}shared_ptr<int> sp5(new int(100));test(sp5);cout << "sp5.use_count()" << sp5.use_count() << endl;return 0;}/*p2.use_count() = 2p1.use_count() = 2p1.reset()p2.use_count()= 1p1.use_count() = 0p1 is emptyp2 is not emptyp2.reset()p2.use_count()= 0p2 is emptytest sp.use_count()2sp5.use_count()1*/
  1. 獲取原始指針

當(dāng)需要獲取原始指針時(shí),可以通過(guò)get方法來(lái)返回原始指針,代碼如下所示:

std::shared_ptr<int> ptr(new int(1));int *p = ptr.get(); //萬(wàn)一不小心 delete p;

謹(jǐn)慎使用p.get()的返回值,如果你不知道其危險(xiǎn)性則永遠(yuǎn)不要調(diào)用get()函數(shù)。?

p.get()的返回值就相當(dāng)于一個(gè)裸指針的值,不合適的使用這個(gè)值,上述陷阱的所有錯(cuò)誤都有可能發(fā)生, 遵守以下幾個(gè)約定: 不要保存p.get()的返回值 ,無(wú)論是保存為裸指針還是shared_ptr都是錯(cuò)誤的 保存為裸指針不知什么時(shí)候就會(huì)變成空懸指針,保存為shared_ptr則產(chǎn)生了獨(dú)立指針 不要delete p.get()的返回值 ,會(huì)導(dǎo)致對(duì)一塊內(nèi)存delete兩次的錯(cuò)誤

  1. 指定刪除器

如果用shared_ptr管理非new對(duì)象或是沒有析構(gòu)函數(shù)的類時(shí),應(yīng)當(dāng)為其傳遞合適的刪除器。

#include <iostream>#include <memory>using namespace std;void DeleteIntPtr(int *p) {cout << "call DeleteIntPtr" << endl;delete p;}int main(){std::shared_ptr<int> p(new int(1), DeleteIntPtr);std::shared_ptr<int> p2(new int(1), [](int *p) {cout << "call lambda1 delete p" << endl;delete p;});std::shared_ptr<int> p3(new int[10], [](int *p) {cout << "call lambda2 delete p" << endl;delete [] p; // 數(shù)組刪除});return 0;}/*call lambda2 delete pcall lambda1 delete pcall DeleteIntPtr*/

當(dāng)p的引用計(jì)數(shù)為0時(shí),自動(dòng)調(diào)用刪除器DeleteIntPtr來(lái)釋放對(duì)象的內(nèi)存。刪除器可以是一個(gè)lambda表達(dá) 式,上面的寫法可以改為:

std::shared_ptr<int> p(new int(1), [](int *p) {cout << "call lambda delete p" << endl;delete p;});

當(dāng)我們用shared_ptr管理動(dòng)態(tài)數(shù)組時(shí),需要指定刪除器,因?yàn)?code>shared_ptr的默認(rèn)刪除器不支持?jǐn)?shù)組對(duì) 象,代碼如下所示:

std::shared_ptr<int> p3(new int[10], [](int *p) { delete [] p;});
  • 智能指針什么時(shí)候需要指定刪除器

在需要 delete 以外的析構(gòu)行為的時(shí)候用. 因?yàn)?shared_ptr 在引用計(jì)數(shù)為 0 后默認(rèn)調(diào)用 delete ptr; 如果不滿足需求就要提供定制的刪除器.

一些場(chǎng)景:

  • 資源不是 new 出來(lái)的(一般也意味著不能 delete), 比如可能是 malloc 出來(lái)的

  • 資源是被第三方庫(kù)管理的 (第三方提供 資源獲取 和 資源釋放 接口, 那么要么寫一個(gè) wrapper 類要么就提供定制的 deleter)

  • 資源不是 RAII 的, 意味著析構(gòu)函數(shù)不會(huì)把資源完全釋放掉...也就是單純 delete 還不夠, 還得做額外的操作比如你的 end_connection 的例子. 雖然我覺得這個(gè)是 bad practice

使用shared_ptr要注意的問(wèn)題

  1. 不要用一個(gè)原始指針初始化多個(gè)shared_ptr,例如下面錯(cuò)誤范例:

int *ptr = new int;
shared_ptr<int> p1(ptr);
shared_ptr<int> p2(ptr); // 邏輯錯(cuò)誤
  1. 不要在函數(shù)實(shí)參中創(chuàng)建shared_ptr,對(duì)于下面的寫法:

function(shared_ptr<int>(new int), g()); //有缺陷

因?yàn)镃++的函數(shù)參數(shù)的計(jì)算順序在不同的編譯器不同的約定下可能是不一樣的,一般是從右到左,但也 可能從左到右,所以,可能的過(guò)程是先new int,然后調(diào)用g(),如果恰好g()發(fā)生異常,而shared_ptr還 沒有創(chuàng)建, 則int內(nèi)存泄漏了,正確的寫法應(yīng)該是先創(chuàng)建智能指針,代碼如下:

shared_ptr<int> p(new int);
function(p, g());
  • 形參和實(shí)參的區(qū)別和聯(lián)系

  1. 形參變量只有在函數(shù)被調(diào)用時(shí)才會(huì)分配內(nèi)存,調(diào)用結(jié)束后,立刻釋放內(nèi)存,所以形參變量只有在函數(shù)內(nèi)部有效,不能在函數(shù)外部使用。

  2. 實(shí)參可以是常量、變量、表達(dá)式、函數(shù)等,無(wú)論實(shí)參是何種類型的數(shù)據(jù),在進(jìn)行函數(shù)調(diào)用時(shí),它們都必須有確定的值,以便把這些值傳送給形參,所以應(yīng)該提前用賦值、輸入等辦法使實(shí)參獲得確定值。

  3. 實(shí)參和形參在數(shù)量上、類型上、順序上必須嚴(yán)格一致,否則會(huì)發(fā)生“類型不匹配”的錯(cuò)誤。當(dāng)然,如果能夠進(jìn)行自動(dòng)類型轉(zhuǎn)換,或者進(jìn)行了強(qiáng)制類型轉(zhuǎn)換,那么實(shí)參類型也可以不同于形參類型。

  4. 函數(shù)調(diào)用中發(fā)生的數(shù)據(jù)傳遞是單向的,只能把實(shí)參的值傳遞給形參,而不能把形參的值反向地傳遞給實(shí)參;換句話說(shuō),一旦完成數(shù)據(jù)的傳遞,實(shí)參和形參就再也沒有瓜葛了,所以,在函數(shù)調(diào)用過(guò)程中,形參的值發(fā)生改變并不會(huì)影響實(shí)參。

請(qǐng)看下面的例子:

#include <stdio.h>//計(jì)算從m加到n的值
int sum(int m, int n) {int i;for (i = m+1; i <= n; ++i) {m += i;}return m;
}int main() {int a, b, total;printf("Input two numbers: ");scanf("%d %d", &a, &b);total = sum(a, b);printf("a=%d, b=%d\n", a, b);printf("total=%d\n", total);return 0;
}
/*
運(yùn)行結(jié)果:
Input two numbers: 1 100
a=1, b=100
total=5050
*/

在這段代碼中,函數(shù)定義處的 m、n 是形參,函數(shù)調(diào)用處的 a、b 是實(shí)參。通過(guò) scanf() 可以讀取用戶輸入的數(shù)據(jù),并賦值給 a、b,在調(diào)用 sum() 函數(shù)時(shí),這份數(shù)據(jù)會(huì)傳遞給形參 m、n。

從運(yùn)行情況看,輸入 a 值為 1,即實(shí)參 a 的值為 1,把這個(gè)值傳遞給函數(shù) sum() 后,形參 m 的初始值也為 1,在函數(shù)執(zhí)行過(guò)程中,形參 m 的值變?yōu)?5050。函數(shù)運(yùn)行結(jié)束后,輸出實(shí)參 a 的值仍為 1,可見實(shí)參的值不會(huì)隨形參的變化而變化。

  1. 通過(guò)shared_from_this()返回this指針。不要將this指針作為shared_ptr返回出來(lái),因?yàn)閠his指針 本質(zhì)上是一個(gè)裸指針,因此,這樣可能會(huì)導(dǎo)致重復(fù)析構(gòu),看下面的例子。

//1-1-shared_from_this
#include <iostream>
#include <memory>using namespace std;class A
{
public:shared_ptr<A>GetSelf(){return shared_ptr<A>(this); // 不要這么做}~A(){cout << "Deconstruction A" << endl;}
};int main()
{shared_ptr<A> sp1(new A);shared_ptr<A> sp2 = sp1->GetSelf();cout << "sp1.use_count() = " << sp1.use_count()<< endl;cout << "sp2.use_count() = " << sp2.use_count()<< endl;return 0;
}/*
sp1.use_count() = 1
sp2.use_count() = 1
Deconstruction A
Deconstruction A
*/

在這個(gè)例子中,由于用同一個(gè)指針(this)構(gòu)造了兩個(gè)智能指針sp1sp2,而他們之間是沒有任何關(guān)系 的,在離開作用域之后this將會(huì)被構(gòu)造的兩個(gè)智能指針各自析構(gòu),導(dǎo)致重復(fù)析構(gòu)的錯(cuò)誤。

正確返回this的shared_ptr的做法是:讓目標(biāo)類通過(guò)std::enable_shared_from_this類,然后使用基類的 成員函數(shù)shared_from_this()來(lái)返回this的shared_ptr,如下所示。

//1-1-shared_from_this2
#include <iostream>
#include <memory>using namespace std;class A: public std::enable_shared_from_this<A>
{
public:shared_ptr<A>GetSelf(){return shared_from_this(); //}~A(){cout << "Deconstruction A" << endl;}
};int main()
{// auto spp = make_shared<A>();shared_ptr<A> sp1(new A);shared_ptr<A> sp2 = sp1->GetSelf();  // ok//    shared_ptr<A> sp2;//    {//        shared_ptr<A> sp1(new A);//        sp2 = sp1->GetSelf();  // ok//    }cout << "sp1.use_count() = " << sp1.use_count()<< endl;cout << "sp2.use_count() = " << sp2.use_count()<< endl;return 0;
}
/*
sp1.use_count() = 2
sp2.use_count() = 2
Deconstruction A
*/

weak_ptr章節(jié)我們繼續(xù)講解使用shared_from_this()的原因。

  1. 避免循環(huán)引用。循環(huán)引用會(huì)導(dǎo)致內(nèi)存泄漏,比如:

#include <iostream>
#include <memory>
using namespace std;class A;
class B;class A {
public:std::shared_ptr<B> bptr;~A() {cout << "A is deleted" << endl;}
};class B {
public:std::shared_ptr<A> aptr;~B() {cout << "B is deleted" << endl;  // 析構(gòu)函數(shù)后,才去釋放成員變量}
};int main()
{std::shared_ptr<A> pa;{std::shared_ptr<A> ap(new A);std::shared_ptr<B> bp(new B);ap->bptr = bp;bp->aptr = ap;pa = ap;// 是否可以手動(dòng)釋放呢?
//        ap.reset();ap->bptr.reset(); // 手動(dòng)釋放成員變量才行}cout<< "main leave. pa.use_count()" << pa.use_count() << endl;  // 循環(huán)引用導(dǎo)致ap bp退出了作用域都沒有析構(gòu)return 0;
}/*
B is deleted
main leave. pa.use_count()1
A is deleted
*/

循環(huán)引用導(dǎo)致apbp的引用計(jì)數(shù)為2,在離開作用域之后,apbp的引用計(jì)數(shù)減為1,并不回減為0,導(dǎo) 致兩個(gè)指針都不會(huì)被析構(gòu),產(chǎn)生內(nèi)存泄漏。

解決的辦法是把A和B任何一個(gè)成員變量改為weak_ptr,具體方法見weak_ptr章節(jié)。

  • 什么是循環(huán)引用?

循環(huán)引用(circular reference)是指在編程中,兩個(gè)或多個(gè)對(duì)象之間形成一個(gè)循環(huán)的引用關(guān)系,導(dǎo)致這些對(duì)象之間的內(nèi)存無(wú)法被正確釋放,從而引發(fā)內(nèi)存泄漏。這種情況也被稱為循環(huán)依賴或循環(huán)關(guān)聯(lián)。

unique_ptr獨(dú)占的智能指針

unique_ptr是一個(gè)獨(dú)占型的智能指針,它不允許其他的智能指針共享其內(nèi)部的指針,不允許通過(guò)賦值將 一個(gè)unique_ptr賦值給另一個(gè)unique_ptr。下面的錯(cuò)誤示例。

unique_ptr<T> my_ptr(new T);
unique_ptr<T> my_other_ptr = my_ptr; // 報(bào)錯(cuò),不能復(fù)制

unique_ptr不允許復(fù)制,但可以通過(guò)函數(shù)返回給其他的unique_ptr,還可以通過(guò)std::move來(lái)轉(zhuǎn)移到其 他的unique_ptr,這樣它本身就不再擁有原來(lái)指針的所有權(quán)了。例如

unique_ptr<T> my_ptr(new T); // 正確
unique_ptr<T> my_other_ptr = std::move(my_ptr); // 正確
unique_ptr<T> ptr = my_ptr; // 報(bào)錯(cuò),不能復(fù)制

std::make_shared是c++11的一部分,但std::make_unique不是。它是在c++14里加入標(biāo)準(zhǔn)庫(kù)的。

auto upw1(std::make_unique<Widget>()); // with make func
std::unique_ptr<Widget> upw2(new Widget); // without make func

使用new的版本重復(fù)了被創(chuàng)建對(duì)象的鍵入,但是make_unique函數(shù)則沒有。重復(fù)類型違背了軟件工程的 一個(gè)重要原則:應(yīng)該避免代碼重復(fù),代碼中的重復(fù)會(huì)引起編譯次數(shù)增加,導(dǎo)致目標(biāo)代碼膨脹。

除了unique_ptr的獨(dú)占性, unique_ptr和shared_ptr還有一些區(qū)別,比如

  • unique_ptr可以指向一個(gè)數(shù)組,代碼如下所示

std::unique_ptr<int []> ptr(new int[10]);
ptr[9] = 9;
std::shared_ptr<int []> ptr2(new int[10]); // 這個(gè)是不合法的
  • unique_ptr指定刪除器和shared_ptr有區(qū)別

std::shared_ptr<int> ptr3(new int(1), [](int *p){delete p;}); // 正確
std::unique_ptr<int> ptr4(new int(1), [](int *p){delete p;}); // 錯(cuò)誤

unique_ptr需要確定刪除器的類型,所以不能像shared_ptr那樣直接指定刪除器,可以這樣寫:

std::unique_ptr<int, void(*)(int*)> ptr5(new int(1), [](int *p){delete p;}); //正確

關(guān)于shared_ptr和unique_ptr的使用場(chǎng)景是要根據(jù)實(shí)際應(yīng)用需求來(lái)選擇。如果希望只有一個(gè)智能指針管 理資源或者管理數(shù)組就用unique_ptr,如果希望多個(gè)智能指針管理同一個(gè)資源就用shared_ptr。

#include <iostream>
#include <memory>
using namespace std;struct MyDelete
{void operator()(int *p){cout << "delete" << endl;delete p;}
};int main()
{auto upw1(std::make_unique<int[]>(2));     // with make func  make_unique需要設(shè)置c++14std::unique_ptr<int> upw2(new int); // without make funcupw1[21] = 1;std::unique_ptr<int,MyDelete> ptr2(new int(1));
//    auto ptr(std::make_unique<int, MyDelete>(1));cout << "main finish! " << upw1[1] << endl;return 0;
}/*
main finish! 0
delete
*/

weak_ptr弱引用的智能指針

share_ptr雖然已經(jīng)很好用了,但是有一點(diǎn)share_ptr智能指針還是有內(nèi)存泄露的情況,當(dāng)兩個(gè)對(duì)象相互 使用一個(gè)shared_ptr成員變量指向?qū)Ψ?#xff0c;會(huì)造成循環(huán)引用,使引用計(jì)數(shù)失效,從而導(dǎo)致內(nèi)存泄漏。

weak_ptr 是一種不控制對(duì)象生命周期的智能指針, 它指向一個(gè) shared_ptr 管理的對(duì)象. 進(jìn)行該對(duì)象的內(nèi) 存管理的是那個(gè)強(qiáng)引用的shared_ptr, weak_ptr只是提供了對(duì)管理對(duì)象的一個(gè)訪問(wèn)手段。weak_ptr 設(shè) 計(jì)的目的是為配合 shared_ptr 而引入的一種智能指針來(lái)協(xié)助 shared_ptr 工作, 它只可以從一個(gè) shared_ptr 或另一個(gè) weak_ptr 對(duì)象構(gòu)造, 它的構(gòu)造和析構(gòu)不會(huì)引起引用記數(shù)的增加或減少。weak_ptr 是用來(lái)解決shared_ptr相互引用時(shí)的死鎖問(wèn)題,如果說(shuō)兩個(gè)shared_ptr相互引用,那么這兩個(gè)指針的引 用計(jì)數(shù)永遠(yuǎn)不可能下降為0,資源永遠(yuǎn)不會(huì)釋放。它是對(duì)對(duì)象的一種弱引用,不會(huì)增加對(duì)象的引用計(jì)數(shù), 和shared_ptr之間可以相互轉(zhuǎn)化,shared_ptr可以直接賦值給它,它可以通過(guò)調(diào)用lock函數(shù)來(lái)獲得 shared_ptr。?

weak_ptr沒有重載操作符*和->,因?yàn)樗还蚕碇羔?#xff0c;不能操作資源,主要是為了通過(guò)shared_ptr獲得 資源的監(jiān)測(cè)權(quán),它的構(gòu)造不會(huì)增加引用計(jì)數(shù),它的析構(gòu)也不會(huì)減少引用計(jì)數(shù),純粹只是作為一個(gè)旁觀者 來(lái)監(jiān)視shared_ptr中管理的資源是否存在。weak_ptr還可以返回this指針和解決循環(huán)引用的問(wèn)題。

weak_ptr的基本用法

  1. 通過(guò)use_count()方法獲取當(dāng)前觀察資源的引用計(jì)數(shù),如下所示:

shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
cout << wp.use_count() << endl; //結(jié)果講輸出1
  1. 通過(guò)expired()方法判斷所觀察資源是否已經(jīng)釋放,如下所示:

shared_ptr<int> sp(new int(10));
weak_ptr<int> wp(sp);
if(wp.expired())cout << "weak_ptr無(wú)效,資源已釋放";
elsecout << "weak_ptr有效";
  1. 通過(guò)lock方法獲取監(jiān)視的shared_ptr,如下所示:

std::weak_ptr<int> gw;
void f()
{if(gw.expired()) {cout << "gw無(wú)效,資源已釋放";}else {auto spt = gw.lock();cout << "gw有效, *spt = " << *spt << endl;}
}int main()
{{auto sp = atd::make_shared<int>(42);gw = sp;f();}f();return 0;
}

weak_ptr返回this指針

shared_ptr章節(jié)中提到不能直接將this指針?lè)祷豷hared_ptr,需要通過(guò)派生 std::enable_shared_from_this類,并通過(guò)其方法shared_from_this來(lái)返回指針,原因是 std::enable_shared_from_this類中有一個(gè)weak_ptr,這個(gè)weak_ptr用來(lái)觀察this智能指針,調(diào)用 shared_from_this()方法是,會(huì)調(diào)用內(nèi)部這個(gè)weak_ptr的lock()方法,將所觀察的shared_ptr返回,再看 前面的范例

//1-1-shared_from_this2
#include <iostream>
#include <memory>using namespace std;class A: public std::enable_shared_from_this<A>
{
public:shared_ptr<A>GetSelf(){return shared_from_this(); }~A(){cout << "Deconstruction A" << endl;}
};int main()
{// auto spp = make_shared<A>();shared_ptr<A> sp1(new A);shared_ptr<A> sp2 = sp1->GetSelf();  // ok//    shared_ptr<A> sp2;//    {//        shared_ptr<A> sp1(new A);//        sp2 = sp1->GetSelf();  // ok//    }cout << "sp1.use_count() = " << sp1.use_count()<< endl;cout << "sp2.use_count() = " << sp2.use_count()<< endl;return 0;
}
/*
sp1.use_count() = 2
sp2.use_count() = 2
Deconstruction A
*/

在外面創(chuàng)建A對(duì)象的智能指針和通過(guò)對(duì)象返回this的智能指針都是安全的,因?yàn)閟hared_from_this()是內(nèi) 部的weak_ptr調(diào)用lock()方法之后返回的智能指針,在離開作用域之后,spy的引用計(jì)數(shù)減為0,A對(duì)象會(huì)被析構(gòu),不會(huì)出現(xiàn)A對(duì)象被析構(gòu)兩次的問(wèn)題。

需要注意的是,獲取自身智能指針的函數(shù)盡量在shared_ptr的構(gòu)造函數(shù)被調(diào)用之后才能使用,因?yàn)?enable_shared_from_this內(nèi)部的weak_ptr只有通過(guò)shared_ptr才能構(gòu)造。

weak_ptr解決循環(huán)引用問(wèn)題

在shared_ptr章節(jié)提到智能指針循環(huán)引用的問(wèn)題,因?yàn)橹悄苤羔樀难h(huán)引用會(huì)導(dǎo)致內(nèi)存泄漏,可以通過(guò) weak_ptr解決該問(wèn)題,只要將A或B的任意一個(gè)成員變量改為weak_ptr

#include <iostream>
#include <memory>
using namespace std;class A;
class B;class A {
public:std::weak_ptr<B> bptr; // 修改為weak_ptrint *val;A() {val = new int(1);}~A() {cout << "A is deleted" << endl;delete  val;}
};class B {
public:std::shared_ptr<A> aptr;~B() {cout << "B is deleted" << endl;}
};//weak_ptr 是一種不控制對(duì)象生命周期的智能指針,
void test()
{std::shared_ptr<A> ap(new A);std::weak_ptr<A> wp1 = ap;std::weak_ptr<A> wp2 = ap;cout<< "ap.use_count()" << ap.use_count()<< endl;
}void test2()
{std::weak_ptr<A> wp;{std::shared_ptr<A> ap(new A);wp = ap;}cout<< "wp.use_count()" << wp.use_count() << ", wp.expired():" << wp.expired() << endl;if(!wp.expired()) {// wp不能直接操作對(duì)象的成員、方法std::shared_ptr<A> ptr = wp.lock(); // 需要先lock獲取std::shared_ptr<A>*(ptr->val) = 20;  }
}int main()
{test2();
//    {
//        std::shared_ptr<A> ap(new A);
//        std::shared_ptr<B> bp(new B);
//        ap->bptr = bp;
//        bp->aptr = ap;
//    }cout<< "main leave" << endl;return 0;
}
/*
A is deleted
wp.use_count()0, wp.expired():1
main leave
*/

這樣在對(duì)B的成員賦值時(shí),即執(zhí)行bp->aptr=ap;時(shí),由于aptr是weak_ptr,它并不會(huì)增加引用計(jì)數(shù),所 以ap的引用計(jì)數(shù)仍然會(huì)是1,在離開作用域之后,ap的引用計(jì)數(shù)為減為0,A指針會(huì)被析構(gòu),析構(gòu)后其內(nèi) 部的bptr的引用計(jì)數(shù)會(huì)被減為1,然后在離開作用域后bp引用計(jì)數(shù)又從1減為0,B對(duì)象也被析構(gòu),不會(huì)發(fā) 生內(nèi)存泄漏。

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

  1. weak_ptr在使用前需要檢查合法性。

weak_ptr<int> wp;
{shared_ptr<int> sp(new int(1)); //sp.use_count()==1wp = sp; //wp不會(huì)改變引用計(jì)數(shù),所以sp.use_count()==1shared_ptr<int> sp_ok = wp.lock(); //wp沒有重載->操作符。只能這樣取所指向的對(duì)象
}
shared_ptr<int> sp_null = wp.lock(); //sp_null .use_count()==0;

因?yàn)樯鲜龃a中sp和sp_ok離開了作用域,其容納的K對(duì)象已經(jīng)被釋放了。 得到了一個(gè)容納NULL指針的sp_null對(duì)象。在使用wp前需要調(diào)用wp.expired()函數(shù)判斷一下。 因?yàn)閣p還仍舊存在,雖然引用計(jì)數(shù)等于0,仍有某處“全局”性的存儲(chǔ)塊保存著這個(gè)計(jì)數(shù)信息。直到最后 一個(gè)weak_ptr對(duì)象被析構(gòu),這塊“堆”存儲(chǔ)塊才能被回收。

如果shared_ptr sp_ok和weak_ptr wp;屬于同一個(gè)作用域呢?如下所示:

weak_ptr<int> wp;
shared_ptr<int> sp_ok;
{shared_ptr<int> sp(new int(1)); //sp.use_count()==1wp = sp; //wp不會(huì)改變引用計(jì)數(shù),所以sp.use_count()==1sp_ok = wp.lock(); //wp沒有重載->操作符。只能這樣取所指向的對(duì)象
}
if(wp.expired()) {cout << "shared_ptr is destroy" << endl;
} else {cout << "shared_ptr no destroy" << endl;
}/*
shared_ptr no destroy
*/
http://www.risenshineclean.com/news/23024.html

相關(guān)文章:

  • 期刊網(wǎng)站建設(shè)湘潭網(wǎng)頁(yè)設(shè)計(jì)
  • 什么網(wǎng)站做ppt模板百度電話號(hào)碼查詢平臺(tái)
  • 盧灣企業(yè)微信網(wǎng)站制作seo實(shí)戰(zhàn)密碼在線閱讀
  • 手機(jī)網(wǎng)站設(shè)計(jì)案濟(jì)南百度快照推廣公司
  • 基礎(chǔ)建設(shè)龍頭股seo做的比較牛的公司
  • 網(wǎng)站效果圖怎么做seo查詢愛站
  • 怎么申請(qǐng)免費(fèi)企業(yè)郵箱賬號(hào)上海優(yōu)化公司有哪些
  • 服務(wù)專業(yè)建設(shè)武漢官網(wǎng)優(yōu)化公司
  • 做網(wǎng)站費(fèi)用多少錢域名解析ip地址
  • 小熊源碼網(wǎng)新網(wǎng)站百度seo如何做
  • 建設(shè)招標(biāo)網(wǎng)網(wǎng)站網(wǎng)站關(guān)鍵詞優(yōu)化網(wǎng)站推廣
  • 自己做網(wǎng)站 搜索功能開發(fā)杭州網(wǎng)站seo優(yōu)化
  • 滄州手機(jī)建站哪家好濟(jì)南seo外包服務(wù)
  • dw做網(wǎng)站怎么設(shè)置頁(yè)面音樂(lè)網(wǎng)站大全軟件下載
  • 公司主頁(yè)怎么填寫seo軟件哪個(gè)好
  • 出國(guó)勞務(wù)信息網(wǎng)seo優(yōu)化網(wǎng)站源碼
  • 做公司網(wǎng)站需要服務(wù)器嗎上海關(guān)鍵詞排名提升
  • 一學(xué)一做短視頻網(wǎng)站杭州市優(yōu)化服務(wù)
  • 重慶網(wǎng)站空間鍵詞排名搜索引擎優(yōu)化的定義
  • 廣州各區(qū)優(yōu)化疫情防控措施seo引擎優(yōu)化公司
  • 做任務(wù)的獎(jiǎng)金網(wǎng)站國(guó)際實(shí)時(shí)新聞
  • 國(guó)務(wù)院建設(shè)部網(wǎng)站seo數(shù)據(jù)是什么意思
  • 什么是網(wǎng)站名稱文件夾寵物美容師寵物美容培訓(xùn)學(xué)校
  • 上海專業(yè)網(wǎng)站建設(shè)機(jī)構(gòu)線上營(yíng)銷平臺(tái)有哪些
  • 哪家公司建設(shè)網(wǎng)站嘉興關(guān)鍵詞優(yōu)化報(bào)價(jià)
  • 網(wǎng)站建設(shè)鼠標(biāo)移動(dòng)變顏色百度seo
  • 做網(wǎng)站框架搭建的人優(yōu)化方法
  • 沒有服務(wù)器怎么做網(wǎng)站seo排名賺能賺錢嗎
  • wamp做的網(wǎng)站外網(wǎng)怎么訪問(wèn)長(zhǎng)春seo顧問(wèn)
  • 鄭州做旅游網(wǎng)站品牌廣告文案