最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++Smart Pointer 智能指針詳解

 更新時間:2022年03月14日 11:42:52   作者:山頂夕景  
這篇文章主要為大家詳細介紹了C++Smart Pointer 智能指針,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

一、為啥使用智能指針呢

標準庫中的智能指針:
std::auto_ptr    --single ownership  (C++98中出現(xiàn),缺陷較多,被摒棄)
std::unique_ptr  --single ownership  (C++11替代std::auto_ptr,用于單線程)
std::shared_ptr  --shared ownership  (C++11,用于多線程)
std::weak_ptr    --temp/no ownership (C++11)
Introduced in C++ 11
Defined in <memory> header.

首先看一個下面的栗子,左邊是木有使用智能指針的情況,當(dāng)執(zhí)行foo()函數(shù),其中的e指針會在bar(e)時傳入bar函數(shù),但是在bar函數(shù)結(jié)束后沒有人為delete e時,就會導(dǎo)致內(nèi)存泄漏;但是在右邊的栗子中,使用了unique_ptr智能指針(single ownership),就能防止內(nèi)存泄漏。

在這里插入圖片描述

智能指針主要用于管理在堆上分配的內(nèi)存,它將普通的指針封裝為一個棧對象。當(dāng)棧對象的生存周期結(jié)束后,會在析構(gòu)函數(shù)中釋放掉申請的內(nèi)存,從而防止內(nèi)存泄漏。

  • auto_ptr智能指針:(C++11出來前只有這種智能指針)當(dāng)對象拷貝或者賦值后,前面的對象就懸空了。
  • unique_ptr智能指針:防止智能指針拷貝和復(fù)制。
  • shared_ptr智能指針:通過引用計數(shù)的方式來實現(xiàn)多個shared_ptr對象之間共享資源。
  • weak_ptr智能指針:可以從一個shared_ptr或另一個weak_ptr對象構(gòu)造,它的構(gòu)造和析構(gòu)不會引起引用記數(shù)的增加或減少。

注意:每一種智能指針都可以增加內(nèi)存的引用計數(shù)。

  • 智能指針分為兩類:
    • 一種是可以使用多個智能指針管理同一塊內(nèi)存區(qū)域,每增加一個智能指針,就會增加1次引用計數(shù),
    • 另一類是不能使用多個智能指針管理同一塊內(nèi)存區(qū)域,通俗來說,當(dāng)智能指針2來管理這一塊內(nèi)存時,原先管理這一塊內(nèi)存的智能指針1只能釋放對這一塊指針的所有權(quán)(ownership)。
  • 按照這個分類標準,auto_ptr unique_ptr weak_ptr屬于后者,shared_ptr屬于前者。

shared_ptr進行初始化時不能將一個普通指針直接賦值給智能指針,因為一個是指針,一個是類??梢酝ㄟ^make_shared函數(shù)或者通過構(gòu)造函數(shù)傳入普通指針。并可以通過get函數(shù)獲得普通指針。

#include <string>
#include <memory>
using namespace std;
class report
{
private:
    string str;
public:
    report(const string s):str(s) //構(gòu)造方法
    {
        cout<<"1 report Object  has been build!"<<endl;
    }
    ~report()
    {
        cout<<"3 report Object  deleted!"<<endl;
    }
    void talk()
    {
        cout<<str<<endl;
    }
};
int main()
{
    string talk="2 hello,this is a test!";
    {
        auto_ptr<report> ptr(new report(talk));
        ptr->talk();
    }
    {
        shared_ptr<report> ptr(new report(talk));
        ptr->talk();
    }
    {
        unique_ptr<report> ptr(new report(talk));
        ptr->talk();
    }
    return 0;
}

在這里插入圖片描述

二、shared_ptr智能指針

shared_ptr實現(xiàn)了共享擁有的概念,利用“引用計數(shù)”來控制堆上對象的生命周期。

share_ptr的生命周期:

在這里插入圖片描述

原理:在初始化的時候引用計數(shù)設(shè)為1,每當(dāng)被拷貝或者賦值的時候引用計數(shù)+1,析構(gòu)的時候引用計數(shù)-1,直到引用計數(shù)被減到0,那么就可以delete掉對象的指針了。他的構(gòu)造方式主要有以下三種:

shared_ptr<Object> ptr;
shared_ptr<Object> ptr(new Object);
shared_ptr<Object> ptr(new Object, [=](Object *){ //回收資源時調(diào)用的函數(shù) });
auto ptr = make_shared<Object>(args);
  • 第一種空構(gòu)造,沒有指定shared_ptr管理的堆上對象的指針,所以引用計數(shù)為0,后期可以通過reset()成員函數(shù)來指定其管理的堆上對象的指針,reset()之后引用計數(shù)設(shè)為1。
  • 第二種是比較常見的構(gòu)造方式,構(gòu)造函數(shù)里面可以放堆上對象的指針,也可以放其他的智能指針(如weak_ptr)。
  • 第三種構(gòu)造方式指定了shared_ptr在析構(gòu)自己所保存的堆上對象的指針時(即引用計數(shù)為0時)所要調(diào)用的函數(shù),這說明我們可以自定義特定對象的特定析構(gòu)方式。同樣的,reset()成員函數(shù)也可以指定析構(gòu)時調(diào)用的指定函數(shù)。
  • 第四種方法:較常見,構(gòu)造shared_ptr的方式(最安全):
auto ptr = make_shared<Object>(args);

上面第四種方法,使用標準庫里邊的make_shared<>()模板函數(shù)。該函數(shù)會調(diào)用模板類的構(gòu)造方法,實例化一個堆上對象,然后將保存了該對象指針的shared_ptr返回。參數(shù)是該類構(gòu)造函數(shù)的參數(shù),所以使用make_shared<>()就好像單純地在構(gòu)造該類對象一樣。auto是C++11的一個關(guān)鍵字,可以在編譯期間自動推算變量的類型,在這里就是shared_ptr<Object>類型。

在這里插入圖片描述

shared_ptr的其他成員函數(shù):

use_count()	//返回引用計數(shù)的個數(shù)
unique()	//返回是否是獨占所有權(quán)(use_count是否為1)
swap()		//交換兩個shared_ptr對象(即交換所擁有的對象,引用計數(shù)也隨之交換)
reset()		//放棄內(nèi)部對象的所有權(quán)或擁有對象的變更, 會引起原有對象的引用計數(shù)的減少

三、unique_ptr智能指針

注意unique_ptr是single ownership的,不能拷貝。其構(gòu)造方式如下:

在這里插入圖片描述

unique_ptr的生命周期:

在這里插入圖片描述

四、weak_ptr智能指針

在這里插入圖片描述

五、智能指針怎么解決交叉引用,造成的內(nèi)存泄漏

結(jié)論:創(chuàng)建對象時使用shared_ptr強智能指針指向,其余情況都使用weak_ptr弱智能指針指向。

5.1 交叉引用的栗子:

當(dāng)A類中有一個指向B類的shared_ptr強類型智能指針,B類中也有一個指向A類的shared_ptr強類型智能指針。

main函數(shù)執(zhí)行后有兩個強智能指針指向了對象A,對象A的引用計數(shù)為2,B類也是:

#include <iostream>
#include <memory>
using namespace std;
class B;
class A{
public:
    shared_ptr<B> _bptr;
};
class B{
public:
    shared_ptr<A> _aptr;
};
int main(){
    shared_ptr<A> aptr(new A());
    shared_ptr<B> bptr(new B());
    aptr->_bptr = bptr;
    bptr->_aptr = aptr;
    return 0;
}

在這里插入圖片描述

而當(dāng)主函數(shù)mainreturn返回后,對象A的引用計數(shù)減一變?yōu)?(aptr沒指向A對象了),B對象也是,引用計數(shù)不為0,即不能析構(gòu)2個對象釋放內(nèi)存,造成內(nèi)存泄漏。

5.2 解決方案

將類A和類B中的shared_ptr強智能指針都換成weak_ptr弱智能指針;

class A{
public:
    weak_ptr<B> _bptr;
};
class B{
public:
    weak_ptr<A> _aptr;
};

weak_ptr弱智能指針,雖然有引用計數(shù),但實際上它并不增加計數(shù),而是只觀察對象的引用計數(shù)。所以此時對象A的引用計數(shù)只為1,對象B的引用計數(shù)也只為1。

在這里插入圖片描述

六、智能指針的注意事項

  • 避免同一塊內(nèi)存綁定到多個獨立創(chuàng)建的shared_ptr上,因此要不使用相同的內(nèi)置指針初始化(或reset)多個智能指針,不要混合使用智能指針和普通指針,堅持只用智能指針。
  • 不delete get() 函數(shù)返回的指針,因為這樣操作后,shared_ptr并不知道它管理的內(nèi)存被釋放了,會造成shared_ptr重復(fù)析構(gòu)。
  • 不使用 get()函數(shù)初始化或(reset)另外的智能指針。
shared_ptr<int> p = make_share<int> (42);
int *q = p.get();
{
  shared_ptr<int>(q); 
} // 程序塊結(jié)束,q被銷毀,指向的內(nèi)存被釋放。
int foo = *p; //  出錯,p指向的內(nèi)存已經(jīng)被q釋放,這是用get() 初始化另外的智能指針惹得禍。
// 請記住,永遠不要用get初始化另外一個智能指針。

能使用unique_ptr時就不要使用share_ptr指針(后者需要保證線程安全,所以在賦值or銷毀時overhead開銷更高)。

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!         

您可能感興趣的文章:

相關(guān)文章

  • 自己簡單封裝的一個CDialog類實例

    自己簡單封裝的一個CDialog類實例

    這篇文章主要介紹了自己簡單封裝的一個CDialog類,實例分析了自定義封裝CDialog類的相關(guān)技巧,比較簡單易懂,需要的朋友可以參考下
    2015-04-04
  • linux下實現(xiàn)的2048游戲示例分享

    linux下實現(xiàn)的2048游戲示例分享

    這篇文章主要介紹了linux下實現(xiàn)的2048游戲示例,需要的朋友可以參考下
    2014-04-04
  • VS2019上配置CUDA的環(huán)境步驟

    VS2019上配置CUDA的環(huán)境步驟

    本文主要介紹了VS2019上配置CUDA的環(huán)境步驟,文中通過圖文示例介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實現(xiàn)

    詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實現(xiàn)

    這篇文章主要介紹了詳解約瑟夫環(huán)問題及其相關(guān)的C語言算法實現(xiàn),也是ACM當(dāng)中經(jīng)常會引用到的基礎(chǔ)題目,文中共介紹了三種C語言解答,需要的朋友可以參考下
    2015-08-08
  • C++ decltype類型說明符

    C++ decltype類型說明符

    在C++中,decltype作為操作符,用于查詢表達式的數(shù)據(jù)類型。decltype在C++11標準制定時引入,主要是為泛型編程而設(shè)計,以解決泛型編程中,由于有些類型由模板參數(shù)決定,而難以(甚至不可能)表示之的問題。
    2016-03-03
  • C++控制臺實現(xiàn)掃雷游戲

    C++控制臺實現(xiàn)掃雷游戲

    這篇文章主要為大家詳細介紹了C++控制臺實現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++ WideCharToMultiByte()函數(shù)案例詳解

    C++ WideCharToMultiByte()函數(shù)案例詳解

    這篇文章主要介紹了C++ WideCharToMultiByte()函數(shù)案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 實例講解在C++的函數(shù)中變量參數(shù)及默認參數(shù)的使用

    實例講解在C++的函數(shù)中變量參數(shù)及默認參數(shù)的使用

    這篇文章主要介紹了在C++的函數(shù)中變量參數(shù)及默認參數(shù)的使用,是C++函數(shù)入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2016-01-01
  • 結(jié)合C++11的新特性來解析C++中的枚舉與聯(lián)合

    結(jié)合C++11的新特性來解析C++中的枚舉與聯(lián)合

    這篇文章主要介紹了C++編程中的枚舉與聯(lián)合,結(jié)合了范圍(或強類型)enum class類型等C++11的新特性來講解,需要的朋友可以參考下
    2016-01-01
  • C++中map和set封裝實現(xiàn)示例

    C++中map和set封裝實現(xiàn)示例

    我們知道,map與set所使用的都是紅黑樹,下面這篇文章主要給大家介紹了關(guān)于C++中map和set封裝實現(xiàn)的相關(guān)資料,文中通過圖文以及實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02

最新評論

上蔡县| 本溪市| 清苑县| 阜阳市| 射阳县| 泌阳县| 平乐县| 兴义市| 新兴县| 建始县| 广东省| 连城县| 江津市| 郎溪县| 永吉县| 洛南县| 湘阴县| 应用必备| 乌兰察布市| 巩义市| 柯坪县| 新邵县| 偏关县| 璧山县| 锡林浩特市| 江西省| 丰都县| 通榆县| 宜宾市| 苏尼特左旗| 中山市| 宜川县| 瑞昌市| 金川县| 集贤县| 内江市| 东乡| 横峰县| 长寿区| 图木舒克市| 平湖市|