日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

智能指针的相关讲解

發(fā)布時(shí)間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 智能指针的相关讲解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1.new和delete操作符
      • 1)new運(yùn)算符做了兩件事
      • 2)delete也做了兩件事
      • 3)補(bǔ)充:
    • 2.shared_ptr
      • 1)概念
      • 2)一般形式
      • 3)常規(guī)初始化(shared_ptr和new配合使用)
      • 4)make_shared函數(shù)
      • 5)shared_ptr引用計(jì)數(shù)的增加和減少
      • 6)shared_ptr指針常用操作
        • 1.use_count函數(shù)
        • 2.unique成員函數(shù)
        • 3.reset成員函數(shù)
        • 4.*解引用
        • 5.get成員函數(shù)
        • 6.swap成員函數(shù)
        • 7.=nullptr
        • 8.智能指針名字作為判斷條件
        • 9.指定刪除器和數(shù)組問(wèn)題
    • 3.weak_ptr
      • 1)簡(jiǎn)介
      • 2)常用操作
        • 1.use_count函數(shù)
        • 2.expired函數(shù)
        • 3.reset函數(shù)
        • 4.lock函數(shù)
      • 3)尺寸問(wèn)題
    • 4.shared_ptr使用場(chǎng)景、陷阱、性能分析與使用建議
      • 1)std::shared_ptr使用場(chǎng)景
      • 2)std::shared_ptr使用陷阱分析
        • 1.慎用裸指針
        • 2.慎用get返回的指針
        • 3.用enable_shared_from_this返回this
        • 4.避免循環(huán)引用
      • 3)性能分析
        • 1.尺寸問(wèn)題
        • 2.移動(dòng)語(yǔ)義
      • 4)補(bǔ)充說(shuō)明和使用建議
    • 5.unique_ptr簡(jiǎn)介與常用操作
      • 1)unique_ptr簡(jiǎn)介
      • 2)unique_ptr常用操作
        • 1.unique_ptr不支持的操作
        • 2.移動(dòng)語(yǔ)義
        • 3.release成員函數(shù)
        • 4.reset成員函數(shù)
        • 5.=nullptr
        • 6.指向一個(gè)數(shù)組
        • 7.get成員函數(shù)
        • 8.*解引用
        • 9.swap成員函數(shù)
        • 10.智能指針名字作為判斷條件
        • 11.轉(zhuǎn)換成shared_ptr類(lèi)型
      • 3)返回unique_ptr
      • 4)刪除器
      • 5)尺寸問(wèn)題
    • 6.智能指針總結(jié)
      • 1)設(shè)計(jì)思想
      • 2)auto_ptr為什么被廢棄
      • 3)智能指針的選擇

1.new和delete操作符

1)new運(yùn)算符做了兩件事

  • ①分配內(nèi)存(new就是通過(guò)operate new來(lái)分配內(nèi)存的)
  • ②調(diào)用構(gòu)造函數(shù)初始化該內(nèi)存

2)delete也做了兩件事

  • ①調(diào)用析構(gòu)函數(shù)
  • ②釋放內(nèi)存(delete就是通過(guò)operate delete()來(lái)釋放內(nèi)存的)

3)補(bǔ)充:

delete [ ]pA中,C++會(huì)多分配4字節(jié)的大小專(zhuān)門(mén)專(zhuān)門(mén)保存數(shù)組的大小,在delete [ ] 時(shí)就可以去除這個(gè)數(shù)組大小的數(shù)字,就知道了需要調(diào)用析構(gòu)函數(shù)多少次

2.shared_ptr

1)概念

  • 共享指針,多個(gè)指針指向同一個(gè)對(duì)象,最后一個(gè)指針被銷(xiāo)毀時(shí),這個(gè)對(duì)象就會(huì)被釋放

2)一般形式

  • shared_ptr<指向的類(lèi)型>智能指針名
  • shared_ptr<string.>p1; //這是一個(gè)指向string的智能指針,名字為p1

3)常規(guī)初始化(shared_ptr和new配合使用)

①常規(guī)

shared_ptr<int>pi(new int(100)); //pi指向一個(gè)值為100的int數(shù)據(jù) shared_ptr<int>pi2 = new int(100);//這個(gè)寫(xiě)法不行,智能指針必須是explicit,是不可以進(jìn)行隱式類(lèi)型轉(zhuǎn)換的,必須用直接初始化方式,而待等號(hào)一般都要表示隱式類(lèi)型轉(zhuǎn)換

②對(duì)于返回值為shared_ptr<int.>類(lèi)型,看看下面的范例:

shared_ptr<int> makes(int value) {return new int(value);//不可以,因?yàn)闊o(wú)法把new得到的int*換成shared_ptr }

所以要修改為

shared_ptr<int>makes(int value) {return shared_ptr<int>(new int(value));//可以,顯示使用int*創(chuàng)建shared_ptr<int> }

③裸指針可以用來(lái)初始化shared_ptr,但是這是一種不被推薦的用法,穿插使用容易出問(wèn)題,盡量使用后面會(huì)講到的make_shared

int *pi = new int; shared_ptr<int> p1(pi);

上面的寫(xiě)法不推薦,應(yīng)該直接傳遞new運(yùn)算符,而不是一個(gè)裸指針變量

shared_ptr<int>p1(new int);

4)make_shared函數(shù)

  • 簡(jiǎn)介:被認(rèn)為是最安全和高效的分配和使用shared_ptr智能指針的模板,能在動(dòng)態(tài)內(nèi)存(堆)中分配并初始化一個(gè)對(duì)象,然后返回指向此對(duì)象的shared_ptr
shared_ptr<int>p2 = std::make_shared<int>(100);//這個(gè)shared_ptr指向一個(gè)值為100的整型的內(nèi)存,類(lèi)似int *pi = new int(100); shared_ptr<string>p3 = std::make_shared<string>(5,'a');//5個(gè)字符,類(lèi)似于string mystr(5,'a');注意到,make_shared后圓括號(hào)里的參數(shù)的形式取決于"<>"中的類(lèi)型名,此時(shí)這些參數(shù)必須和string里的某個(gè)構(gòu)造函數(shù)匹配 shared_ptr<int>p4 = make_shared<int>();//p4指向一個(gè)int,int里面保存的值是0,這個(gè)就是值初始化 p4 = make_shared<int>(400);//p4釋放剛才的對(duì)象,重新指向新對(duì)象 auto p5 = std::make_shared<string>(5,'a');//用auto保存make_shared結(jié)果,寫(xiě)法簡(jiǎn)單
  • make_shared使用起來(lái)雖然不錯(cuò),后面還提到自定義刪除器,如果使用make_shared方法生成shared_ptr對(duì)象,那就沒(méi)有辦法自定義刪除器了

5)shared_ptr引用計(jì)數(shù)的增加和減少

1.引用計(jì)數(shù)的增加
每個(gè)shared_ptr都會(huì)記錄有多少個(gè)其他shared_ptr指向相同的對(duì)象
(1)像下面的代碼這樣,p6初始化p7,就會(huì)導(dǎo)致所有指向該對(duì)象(內(nèi)存)的shared_ptr引用計(jì)數(shù)全部增加1

auto p6 = std::make_shared<int>(100);//目前p6所指的對(duì)象只有p6一個(gè)引用者 auto p7(p6);//寫(xiě)成auto p7 = p6;也可以,智能指針復(fù)制,p7和p6指向相同的對(duì)象,此對(duì)象有兩個(gè)引用者

(2)把引用計(jì)數(shù)當(dāng)成實(shí)參往函數(shù)里面?zhèn)鬟f

void myfunc(shared<int>&ptmp)//傳遞引用作為形參,則引用計(jì)數(shù)不會(huì)增加 {return ptmp; }

在main主函數(shù)中,繼續(xù)增加如下代碼

myfunc(p7);//這個(gè)函數(shù)執(zhí)行后,這個(gè)指針的引用計(jì)數(shù)會(huì)恢復(fù)

(3)作為函數(shù)的返回值

shared_ptr<int>myfunc2(shared_ptr<int>&ptmp)//這里是引用,所以計(jì)數(shù)還是2 {return ptmp; }

在主函數(shù)中增加以下代碼

auto p8 = myfunc2(p7);//p8接受myfunc2函數(shù)返回值,那么此時(shí)引用計(jì)數(shù)會(huì)變成3

2.引用計(jì)數(shù)的減少
(1)給shared_ptr賦一個(gè)新值,讓該shared_ptr指向一個(gè)新對(duì)象,在main主函數(shù)中增加以下代碼

p8 = std::make_shared<int>(200);//p8指向新對(duì)象1,p6,p7計(jì)數(shù)從3恢復(fù)為2 p7 = std::make_shared<int>(200);//p7指向新對(duì)象1,p6計(jì)數(shù)的源對(duì)象恢復(fù)計(jì)數(shù)為1 p6 = std::make_shared<int>(200);//p6指向新對(duì)象1,p6指向的原對(duì)象內(nèi)存被釋放

(2)局部的shared_ptr離開(kāi)作用域

auto p6 = std::make_shared<int>(100); auto p7(p6);// myfunc(p7);//進(jìn)入函數(shù)體myfunc中時(shí)有3個(gè)引用計(jì)數(shù),從myfunc中返回時(shí)引用計(jì)數(shù)恢復(fù)為2

(3)當(dāng)一個(gè)shared_ptr引用計(jì)數(shù)為0,他會(huì)Zion給釋放自己所管理的對(duì)象

auto p9 = std::make_shared<int>(100);//只有p9指向該對(duì)象 auto p10 = std::make_shared<int>(100); p9 = p10;//p9指向p10的對(duì)象,該對(duì)象引用計(jì)數(shù)為2,而原來(lái)p9指向的對(duì)象引用計(jì)數(shù)會(huì)變?yōu)?,所以會(huì)被自動(dòng)釋放

6)shared_ptr指針常用操作

1.use_count函數(shù)

用于返回多少個(gè)智能指針指向某個(gè)對(duì)象

shared_ptr<int>myp(new int(100)); int icount = myp.use_count();//1 shared_ptr<int>myp2(myp); icount = myp2.use_count();//2

2.unique成員函數(shù)

是否該智能指針獨(dú)占某個(gè)指向的對(duì)象,,也就是若只有一個(gè)智能指針指向某個(gè)對(duì)象,則unique返回true,否則返回false

shared_ptr<int>myp(new int(100)); if(myp.unique()) //本條件成立 {cout<<"myp unique ok"<<endl; } shared_ptr<int>myp2(myp); if(myp.unique()) {cout<<"myp unique ok"<<endl; }

3.reset成員函數(shù)

(1)當(dāng)reset不帶參數(shù)時(shí)
當(dāng)pi是唯一指向該對(duì)象的指針,則釋放pi所指向的對(duì)象,將pi置空
若pi不是唯一指向該對(duì)象的指針,則不釋放pi所指向的對(duì)象,但指向該對(duì)象引用計(jì)數(shù)會(huì)減1,同時(shí)將pi置空

shared_ptr<int>(new int(100)); pi.reset();//釋放Pi指向的對(duì)象,將pi置空 if(pi == nullptr)//條件成立 {cout<<"pi被置空"<<endl; }

繼續(xù)演示若pi不是唯一指向該對(duì)象的指針的情形

shared_ptr<int>(new int(100)); auto pi2(pi); //pi2引用計(jì)數(shù)現(xiàn)在為2 pi.reset(); //pi被置空,pi2引用計(jì)數(shù)變?yōu)?

(2)當(dāng)reset帶參數(shù)(一般是一個(gè)new出來(lái)的指針)時(shí)
若pi是唯一指向該對(duì)象的指針,則釋放pi所指向的對(duì)象,讓pi指向新內(nèi)存
若pi不是唯一指向該對(duì)象的指針,則不釋放pi指向?qū)ο?#xff0c;但是指向該對(duì)象的引用計(jì)數(shù)會(huì)減1,同時(shí)讓pi指向新內(nèi)存

shared_ptr<int>pi(new int(100)); pi.reset(new int(1));//釋放原內(nèi)存,指向新內(nèi)存

演示若pi不是唯一指向該對(duì)象的指針的情形

shared_ptr<int>pi(new int(100)); auto pi2(pi); pi.reset(new int(1));//現(xiàn)在pi引用計(jì)數(shù)為1,pi2引用計(jì)數(shù)也為1 if(pi.unique())//本條件成立 {cout<<"pi unique ok"<<endl; }

(3)空指針也可以通過(guò)reset來(lái)重新初始化

shared_ptr<int>p; p.reset(new int(100));//p指向新內(nèi)存

4.*解引用

獲得p指向的對(duì)象

shared_ptr<int>pother(new int(12345)); char outbuf[1024]; sprintf_s(outbuf,sizeof(outbuf),"%d",*pother);//outbuf中的內(nèi)容就是12345,pother不發(fā)生變化,引用計(jì)數(shù)仍舊為1 OutputDebugStringA(outbuf);//在MyProjectMFC工程中使用F5運(yùn)行,執(zhí)行到這行可以打印輸出outbuf的內(nèi)容

5.get成員函數(shù)

p.get()返回p中保存的指針
小心使用,若智能指針釋放了所指向的對(duì)象,則返回的這個(gè)指針?biāo)赶虻膶?duì)象就變得無(wú)效了

shared_ptr<int>myp(new int(100)); int *p = myp.get(); * p = 45;

6.swap成員函數(shù)

交換兩個(gè)智能指針?biāo)赶虻膶?duì)象

shared_ptr<string>ps1(new string("I love china1!")); shared_ptr<string>ps2(new string("I love china2!")); std::swap(ps1,ps2);//可以這么操作 ps1.swap(ps2);//也可以這么操作

7.=nullptr

  • 將指針指向的引用計(jì)數(shù)減1,若引用計(jì)數(shù)變?yōu)?,則釋放智能指針?biāo)赶虻膶?duì)象
  • 將智能指針置空
shared_ptr<string>ps1(new string("I love china!")); ps1 = nullptr;

8.智能指針名字作為判斷條件

shared_ptr<string> ps1(new string("I love china!")); //若ps1指向一個(gè)對(duì)象,則條件成立 if(ps1)//條件成立 {cout<<"ps1"<<endl;//執(zhí)行 }

9.指定刪除器和數(shù)組問(wèn)題

1)指定刪除器
可以為智能指針定義自己的寫(xiě)的刪除器

void myDeleter(int *p)//自己的刪除器,刪除整型指針用的,當(dāng)p的引用計(jì)數(shù)為0,則自動(dòng)調(diào)用這個(gè)刪除器刪除對(duì)象,釋放內(nèi)存 {delete p; }

在main主函數(shù)中,加入如下代碼:

shared_ptr<int>p(new int(12345),myDeleter);//指定刪除器 shared_ptr<int>p2(p); p2.reset();//p2為nullptr了 p.reset();//調(diào)用自己的刪除器,釋放鎖指向的對(duì)象,同時(shí)p置空

lamdba表達(dá)式也可以定義刪除器

shared_ptr<int>p(new int(12345),[](int*p) {delete p; } p.reset();//會(huì)帶哦用刪除器(lamdba表達(dá)式)

為什么要自己定義刪除器?

當(dāng)默認(rèn)的刪除器處理不了——用shared_ptr管理動(dòng)態(tài)數(shù)組的時(shí)候,需要自己指定自己的刪除器,默認(rèn)的刪除器不支持?jǐn)?shù)組對(duì)象

shared_ptr<int[]>p(new int[10],[](int*p)) {delete[]p; }); p.reset();

如果一個(gè)類(lèi)中帶有析構(gòu)函數(shù),那么必須定義自己的刪除器,否則會(huì)報(bào)異常

class A { public:A(){cout<<""<<endl;}~A(){cout<<""<<endl;} };

在main主函數(shù)中加入如下代碼

shared_ptr<A>pA(new A[10),[](A*p) {delete[]p; }); //還可以這么寫(xiě) shared_ptr<A>pA(new A[10],std::default_delete<A[]>()); //不寫(xiě)刪除器,也可以這么定義 shared_ptr<A[]>pA(new A[]);//<>中加個(gè)[]就行 shared_ptr<int[]>p(new in[10]);

2)指定刪除器的額外說(shuō)明

3.weak_ptr

1)簡(jiǎn)介

  • 用來(lái)輔助shared_ptr工作的
  • 將weak_ptr綁定到shared_ptr并不會(huì)改變shared_ptr的引用計(jì)數(shù)(更確切的說(shuō),weak_ptr的構(gòu)造和析構(gòu)函數(shù)不會(huì)增加或減少鎖指向?qū)ο蟮囊糜?jì)數(shù))
  • weak_ptr的創(chuàng)建一般用make_shared來(lái)初始化
auto pi = make_shared<int>(100); weak_ptr<int>piw(p1);//piw弱共享pi,pi引用計(jì)數(shù)(強(qiáng)引用計(jì)數(shù))不改變,弱引用計(jì)數(shù)會(huì)從0變成1,pi和piw指向相同位置 //也可以這么寫(xiě) weak_ptr<int>piw; piw = pi;//這里是一個(gè)shared_ptr,賦值給一個(gè)weak_ptr,pi和piw兩者指向相同位置
  • 程序員不能通過(guò)weak_ptr直接訪(fǎng)問(wèn)對(duì)象的,必須要用一個(gè)lock的成員函數(shù),lock的功能就是檢查weak_ptr鎖指向的對(duì)象是否還存在,如果存在,lock能夠返回一個(gè)空的shared_ptr
auto pi2 = piw.lock();//強(qiáng)引用(shared_ptr)計(jì)數(shù)會(huì)加1,現(xiàn)在pi是兩個(gè)強(qiáng)引用,兩個(gè)弱引用 if(pi2 != nullptr) {cout<<"所指對(duì)象存在"<<endl; }
  • weak_ptr具備能夠判斷所指向的對(duì)象是否存在的能力

2)常用操作

1.use_count函數(shù)

auto pi = make_shared<int>(100); auto pi2(pi);//pi2類(lèi)型是一個(gè)shared_ptr weak_ptr<int>piw(pi); int isc = piw.use_count();

2.expired函數(shù)

  • 是否過(guò)期的意思,弱該指針的use_count為0,則返回true,否則返回false
pi.reset(); pi2.reset(); if(piw.expired())//如果過(guò)期 {cout<<"piw已經(jīng)過(guò)期"<<endl; }

3.reset函數(shù)

  • 將該弱引用指針設(shè)置為空,不影響指向該對(duì)象的強(qiáng)引用數(shù)量,但指向該對(duì)象的弱引用數(shù)量會(huì)減1
auto pi = make_shared<int>(42); weak_ptr<int>piw(pi); piw.resset(); //pi是一個(gè)強(qiáng)引用,無(wú)弱引用

4.lock函數(shù)

  • 獲得監(jiān)視的shared_ptr,下面是完整的演示
auto p1 = make_shared<int>(42); weak_ptr<int>pw; pw = p1;//用shared_ptr給weak_ptr值,現(xiàn)在p1是1個(gè)強(qiáng)引用1個(gè)弱引用 if(!pw.expired())//如果pw沒(méi)過(guò)期 {auto p2 = pw.lock();//現(xiàn)在p1是2個(gè)強(qiáng)引用1個(gè)弱引用if(p2 != nullptr){cout<<"所指對(duì)象存在"<<endl;} //離開(kāi)這個(gè)范圍,p1的強(qiáng)引用計(jì)數(shù)恢復(fù)為1,弱引用計(jì)數(shù)保持為1 } else//若pw已經(jīng)過(guò)期 {cout<<"pw已經(jīng)過(guò)期"<<endl; }
  • 上面的代碼改造以下,看如下這個(gè)比較完整的演示,引入一個(gè){ }
weak_ptr<int>pw; {auto p1 = make_shared<int>(42);pw = p1;//用shared_ptr給weak_ptr值 }//離開(kāi)這里p1就都失效了 //這里pw這個(gè)weak_ptr就會(huì)過(guò)期了 if(pw.expired())//pw已經(jīng)過(guò)期,進(jìn)入if條件執(zhí)行語(yǔ)句,打印 {cout<<"pw已經(jīng)過(guò)期了"<<endl; }

3)尺寸問(wèn)題

  • weak_ptr的尺寸是裸指針的2倍,其他略

4.shared_ptr使用場(chǎng)景、陷阱、性能分析與使用建議

1)std::shared_ptr使用場(chǎng)景

shared_ptr<int>create0(int value) {return make_shared<int>(value);//返回一個(gè)shared_ptr } void myfunc(int value) {shared_ptr<int>ptmp = create0(10);return;//ptmp離開(kāi)了作用域(ptmp是局部變量),因此他指向的內(nèi)存會(huì)被自動(dòng)釋放 }
  • 在主函數(shù)中,加入如下代碼
    myfunc(12);
  • 現(xiàn)在改造以下myfunc函數(shù)
shared_ptr<int>myfunc(int value) {shared_ptr<int>ptmp = create0(10);return ptmp;//這個(gè)return會(huì)導(dǎo)致引用計(jì)數(shù)遞增,所以ptmp指向的內(nèi)存不會(huì)釋放,者相當(dāng)于返回了一個(gè)ptmp的復(fù)制,ptmp銷(xiāo)毀計(jì)數(shù)-1,return ptmp;使計(jì)數(shù)+1 } //主函數(shù)中,用一個(gè)變量接住返回的shared_ptr指針才會(huì)使計(jì)數(shù)+1 auto p11 = myfunc(12);

2)std::shared_ptr使用陷阱分析

1.慎用裸指針

  • 如果把一個(gè)普通裸指針綁定到了一個(gè)shared_ptr,那么內(nèi)存管理的責(zé)任就交給智能指針,就不應(yīng)該再使用裸指針(內(nèi)置指針)訪(fǎng)問(wèn)shared_ptr指定的內(nèi)存了
shared_ptr<int>myp(new int(100)); proc(myp); *myp = 45;//myp可是shared_ptr<int>類(lèi)型,*表示解引用
  • 但是不要用裸指針初始化多個(gè)shared_ptr對(duì)象,兩個(gè)指針無(wú)關(guān)聯(lián)關(guān)系,釋放裸指針?biāo)赶虻膬?nèi)存要釋放2次,這顯然會(huì)出問(wèn)題
int * pi = new int; shared_ptr<int>p1(pi); shared_ptr<int>p2(pi);

修改為

//可修改為 shared_ptr<int>p1(new int);//大大降低了用pi來(lái)創(chuàng)建p2的可能性

2.慎用get返回的指針

  • get返回的指針不能delete,否則會(huì)產(chǎn)生異常,也不能將其他智能指針綁到get返回的指針上

3.用enable_shared_from_this返回this

  • 看如下代碼
class CT { public:shared_ptr<CT>getself(){return shared_ptr<CT>(this);} };
  • 在main主函數(shù)里面,加入如下代碼
shared_ptr<CT>pct1(new CT); shared_ptr<CT>pct2 = pct1;//沒(méi)問(wèn)題,2個(gè)強(qiáng)引用 //第二句若改成 shared_ptr<CT>pct2 = pct1->getself();//問(wèn)題出現(xiàn)
  • 上面的代碼用同一個(gè)指針構(gòu)造了兩個(gè)智能指針pct1和pct2,兩個(gè)之怎能指針之間沒(méi)有任何關(guān)系,也就是釋放同一個(gè)都西昂內(nèi)存會(huì)釋放兩次,解決方法如下
class CT :public std::enable_shared_from_this<CT>//C++標(biāo)準(zhǔn)庫(kù)提供的類(lèi)模板 { public:shared_ptr<CT>getself(){return shared_ptr_from_this();//通過(guò)這個(gè)方法返回智能指針} }; //主函數(shù)代碼不變 shared_ptr<CT>pct1(new CT); shared_ptr<CT>pct2 = pct1->getself();

4.避免循環(huán)引用

  • 循環(huán)引用會(huì)導(dǎo)致內(nèi)存泄漏
  • 解決辦法:把其中一個(gè)shared_ptr寫(xiě)成weak_ptr
class CB { public:/shared_ptr<CA> m_pas;weak_ptr<CA> m_pas;~CB(){cout<<"~B()執(zhí)行了"<<endl;} }; //主函數(shù)調(diào)用 shared_ptr<CA>pca(new CA); shared_ptr<CB>pcb(new CB); pca->m_pbs = pcb;//現(xiàn)在等價(jià)于指向CB對(duì)象的有兩個(gè)強(qiáng)引用 pcb->m_pas = pca;//因?yàn)閙_pas是弱引用,所以指向CA對(duì)象的只有一個(gè)強(qiáng)引用,離開(kāi)作用域后,先執(zhí)行CA的析構(gòu)函數(shù),后執(zhí)行CB的析構(gòu)函數(shù)

3)性能分析

1.尺寸問(wèn)題

尺寸是裸指針的2倍

2.移動(dòng)語(yǔ)義

  • 全程引用計(jì)數(shù)為1
shared_ptr<int>p1(new int(100));//p1指向該對(duì)象(內(nèi)存) shared_ptr<int>p2(std::move(p1));//移動(dòng)語(yǔ)義 shared_ptr<int>p3; p3 = std::move(p2);

4)補(bǔ)充說(shuō)明和使用建議

make_shared比普通指針的智能效率高,只分配一次內(nèi)存

shared_ptr<string>ps1(new string("I love China!"));//這句話(huà)至少分配兩次內(nèi)存

5.unique_ptr簡(jiǎn)介與常用操作

1)unique_ptr簡(jiǎn)介

  • 獨(dú)占式智能指針
  • unique的一般形式
unique_ptr<指向的對(duì)象類(lèi)型>智能指針變量名

1.常規(guī)初始化

unique_ptr<int>pi2(new int(102));

2.make_unique函數(shù)

  • C++11不支持,C++14才有
unique_ptr<int>p1 = std::make_unique<int>(100); auto p2 = std::make_unique<int>(200); //若不用make_unique,就得像上面常規(guī)初始化那樣寫(xiě)

2)unique_ptr常用操作

1.unique_ptr不支持的操作

  • 不支持復(fù)制和賦值
unique_ptr<string>ps1(new string("I love China!")); unique_ptr<string>ps2(ps1);//不可以,不支持復(fù)制 unique_ptr<string>ps4; ps4 = ps1;//不可以,不支持賦值操作

2.移動(dòng)語(yǔ)義

  • 支持移動(dòng)語(yǔ)義
unique_ptr<string>ps1(new string("I love China!")); unique_ptr<string>ps2 = std::move(ps1);//ps1空了,ps3指向ps1原先所指

3.release成員函數(shù)

  • 放棄對(duì)指針的控制權(quán),返回裸指針,將智能指針?lè)趴铡7祷氐穆阒羔樋梢允止elete釋放,也可以用來(lái)初始化另外一個(gè)智能指針,或者給另外一個(gè)智能指針賦值
/將所有權(quán)從ps1轉(zhuǎn)移(移動(dòng))給ps2 unique_ptr<string>ps1(new string("I love China!")); unique_ptr<string>ps2(ps1.release()); if(ps1 == nullptr) //條件被置空 {cout<<"ps1被置空"<<endl; } /下面這個(gè)語(yǔ)句,內(nèi)存會(huì)泄漏 ps2.release(); /所以要這么修改 string *tempp = ps2.release(); 或者是auto tempp = ps.release() delete tempp;

4.reset成員函數(shù)

和shared_ptr一樣

5.=nullptr

和shared_ptr一樣

6.指向一個(gè)數(shù)組

std::unique_ptr<int[]>ptrarray(new int[10]); ptrarray[0] = 12;//數(shù)組提供索引運(yùn)算符[] ptrarray[2] = 9;

7.get成員函數(shù)

和shared_ptr一樣

8.*解引用

  • 數(shù)組是沒(méi)有*解引用運(yùn)算符的
unique_ptr<string>(new string("I love China!")); const char *p1 = ps1->c_str(); *ps1 = "This is a test !"; const char*p2 = ps1->c_str();//p1和p2是不同的內(nèi)存地址,string內(nèi)部機(jī)制決定的

9.swap成員函數(shù)

和shared_ptr一樣

10.智能指針名字作為判斷條件

若ps1指向一個(gè)對(duì)象,則不為空

11.轉(zhuǎn)換成shared_ptr類(lèi)型

unique_ptr<std::string>ps(new std::string("I love China!")); shared_ptr<string>ps2 = std::move(ps);

3)返回unique_ptr

  • 生成局部對(duì)象的unique_ptr可以返回復(fù)制,因?yàn)橐讳N(xiāo)毀了

4)刪除器

1.指定刪除器
1)范例

void mydeleter(string *pdel) {delete pdel;pdel = nullptr; } /主函數(shù)加入 typdef void(*fp)(string*);//定義一個(gè)函數(shù)指針,類(lèi)型名為fp unique_ptr<string,fp>ps1(new string("I love China!"),mydeleter);

2.補(bǔ)充指定刪除器
shared_ptr的刪除器更靈活,相同類(lèi)型就可以共用刪除器,但是unique_ptr的刪除器不一樣,不靈活

5)尺寸問(wèn)題

通常情況下unique_ptr的尺寸和裸指針一樣,若刪除器是一個(gè)函數(shù),unique_ptr的尺寸就會(huì)發(fā)生變化

6.智能指針總結(jié)

1)設(shè)計(jì)思想

防止忘記內(nèi)存釋放,造成內(nèi)存泄漏

2)auto_ptr為什么被廢棄

不能在容器中保存auto_ptr,也不能從函數(shù)中返回auto_ptr,已經(jīng)被unique_ptr取代

3)智能指針的選擇

優(yōu)先考慮unique_ptr,要使用多個(gè)指向同一個(gè)對(duì)象的指針的話(huà)用shared_ptr

總結(jié)

以上是生活随笔為你收集整理的智能指针的相关讲解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。