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

C++之智能指針初步及棄用auto_ptr的原因分析

 更新時(shí)間:2023年03月23日 14:54:28   作者:Dutkig  
這篇文章主要介紹了C++之智能指針初步及棄用auto_ptr的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

RAII

使用局部對(duì)象來(lái)管理資源的技術(shù)

RAII的原理

RAII的四個(gè)步驟

裸指針存在的問(wèn)題

delete后的指針變量就變成了一個(gè)失效指針(也叫作懸空指針)。

對(duì)于下面的代碼:

void Destroy(Object *op)
{
	delete op;
	delete[] op;
}

Object *op = new Object(10);
Object *arop = new Object[10];

Destroy(op);
Destroy(arop);

因此:

智能指針

智能指針的引入

智能指針是比原始指針更加智能的類(lèi),解決懸空指針多次刪除被指向?qū)ο?,以及資源泄漏問(wèn)題,通常用來(lái)確保指針的壽命和其指向?qū)ο蟮膲勖恢隆?/p>

智能指針雖然很智能,很容易被誤用,智能也是有代價(jià)的。

四種智能指針

  • auto_ptr
  • unqiue_ptr(唯一性智能指針)
  • shared_ptr(共享性智能指針)
  • weak_ptr(管理弱引用)

其中后三個(gè)是C11支持,并且第一個(gè)已經(jīng)被C11棄用。

C98中的auto_ptr所做的事情,就是動(dòng)態(tài)分配對(duì)象以及當(dāng)對(duì)象不再需要時(shí)自動(dòng)執(zhí)行清理。

下面我們首先來(lái)了解一下為什么要將auto_ptr移除的原因:

因?yàn)樵擃?lèi)型的智能指針意義不明確,使用淺拷貝方式時(shí),兩個(gè)對(duì)象擁有同一塊資源:我們模仿源碼的邏輯

了解一下:比如下面的代碼:

class Object
{
    int value;
public:
    Object(int x = 0):value(x){cout<<"Create Object:"<<this<<endl;}
    ~Object(){cout<<"Destroy Object:"<<this<<endl;}

    int  & Value(){return value;}
    const int& Value() const{return value;}
};

template<class _Ty>
class my_auto_ptr
{
private:
    bool _Owns;//所有權(quán)
    _Ty* _Ptr;
public:
    my_auto_ptr(_Ty* p = NULL):_Owns(p != NULL),_Ptr(p){}
    ~my_auto_ptr()
    {
        if(_Owns)
        {
            delete _Ptr;
        }
        _Owns = false;
        _Ptr = NULL;
    }
    _Ty* get() const 
    {
        return _Ptr;
    }
    _Ty* operator->()const
    {
        return get();
    }
    _Ty & operator*()
    {
        return *get();
    }
    void reset(_Ty* p = NULL) 
    {
       if(_Owns)
       {
           delete _Ptr;
       }
       _Ptr = p;
    }
    _Ty * release()const//編譯要通過(guò),要么異變,要么強(qiáng)轉(zhuǎn)成普通指針
    {
        _Ty* tmp = NULL;
        if(_Owns)
        {
            ((my_auto_ptr*)this)->_Owns = false;
            tmp = _Ptr;
            ((my_auto_ptr*)this)->_Ptr = NULL;
        }
        return tmp;
    }
    my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns)
    {
        if(_Owns)
        {
            _Ptr = op._Ptr;
        }
    }
};

void fun()
{
    my_auto_ptr<Object> pobj(new Object(10));//pobj是my_auto_ptr類(lèi)型
    cout<<pobj->Value()<<endl;
    cout<<(*pobj).Value()<<endl;//(*pobj)是Object的堆區(qū)對(duì)象。*(pobj._Ptr).Value()
}
int main()
{
    my_auto_ptr<Object> pobja(new Object(10));
    my_auto_ptr<Object> pobjb(pobja);
}

相關(guān)函數(shù)解釋?zhuān)?/p>

此時(shí)程序必然會(huì)導(dǎo)致程序崩潰引發(fā)異常,主函數(shù)結(jié)束時(shí)對(duì)同一部分資源釋放了兩次,堆內(nèi)存被釋放兩次

那么我們可能會(huì)考慮,將資源轉(zhuǎn)移,即修改拷貝構(gòu)造如下:利用是釋放函數(shù)

my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns),_Ptr(op.release())
    {}

看似好像解決了上面的問(wèn)題,實(shí)則存在隱患

繼續(xù)來(lái)看:下面的代碼存在什么問(wèn)題呢?

void fun(my_auto_ptr<Object> apx)
{
    int x = apx->Value();
    cout<<x<<endl;
}

int main()
{
    my_auto_ptr<Object> pobja(new Object(10));
    
    fun(pobja);

    int a = pobja->Value();
    cout<<a<<endl;
}

上述代碼的執(zhí)行邏輯如下:

  • pobja有兩個(gè)域擁有權(quán)域和指針域,拿pobja初始化形參apx時(shí),會(huì)調(diào)動(dòng)拷貝構(gòu)造函數(shù)
  • apx將自己的擁有權(quán)域設(shè)為1,調(diào)動(dòng)release函數(shù),銷(xiāo)毀了pobja對(duì)象的資源后,返回堆區(qū)對(duì)象的地址,apx接收后將自身的指針域指向原先pobja所指向的堆區(qū)對(duì)象
  • fun函數(shù)結(jié)束,apx局部對(duì)象就會(huì)被析構(gòu),此時(shí)再打印a,對(duì)象其實(shí)已經(jīng)不存在了并且自身早已失去了pobja的擁有權(quán)。

綜上,此時(shí)智能指針的拷貝構(gòu)造函數(shù)的兩種寫(xiě)法:

 my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns)
    {
        if(_Owns)
        {
            _Ptr = op._Ptr;
        }
    }
   
 my_auto_ptr(const my_auto_ptr & op):_Owns(op._Owns),_Ptr(op.release())
    {}
  • 第一種存在的問(wèn)題:Object的資源會(huì)被兩個(gè)釋放兩次
  • 第二種存在的問(wèn)題:解決了第一種問(wèn)題,但是不能解決類(lèi)似于實(shí)參對(duì)象初始化形參時(shí),實(shí)參之前自身的資源丟失的問(wèn)題,找不著了,因?yàn)檫@種情況太過(guò)于隱蔽,容易出錯(cuò),所以auto_ptr作為函數(shù)參數(shù)傳遞時(shí)一定要避免的?;蛟S你想到加上引用解決上面的問(wèn)題,但是仔細(xì)思考后發(fā)現(xiàn),我們并不知道函數(shù)對(duì)傳入的傳入的auto_ptr做了什么,如果當(dāng)中的某些操作使其失去了對(duì)對(duì)象的所有權(quán),那么這還可能會(huì)導(dǎo)致致命的執(zhí)行期錯(cuò)誤。獲取再加上const 才是個(gè)不錯(cuò)的選擇。

因此,C11標(biāo)準(zhǔn)之前的auto_ptr這個(gè)智能指針不被廣泛使用的原因就是:在某些應(yīng)用場(chǎng)景下,拷貝構(gòu)造函數(shù)的意義不明確,同理賦值語(yǔ)句也是這個(gè)道理,意義同樣不明確,因?yàn)镃11標(biāo)準(zhǔn)之前并不存在移動(dòng)賦值和移動(dòng)構(gòu)造的概念,還有就是之前談到的一個(gè)對(duì)象和一組對(duì)象的問(wèn)題,對(duì)于自定義類(lèi)型而言,auto_ptr的析構(gòu)函數(shù)僅能夠析構(gòu)一個(gè)對(duì)象,不能夠處理一組對(duì)象的情況,這些都是尚未解決的問(wèn)題。

于是在C11中棄用,C17標(biāo)準(zhǔn)中直接移除。 

歷史淵源:

在STL庫(kù)之前,有一個(gè)功能更加強(qiáng)大的boost庫(kù),STL為了與其抗衡,應(yīng)急制造了STL,但制作的不夠完善,由此因?yàn)镾TL未解決auto_ptr的問(wèn)題,因此STl內(nèi)的容器vector和list都不想和auto_ptr建立聯(lián)系。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C++?STL?中的數(shù)值算法示例講解

    C++?STL?中的數(shù)值算法示例講解

    本片文章講解了C++STL?中的數(shù)值算法,包含iota、accumulate、adjacent_difference、inner_product、partial_sum這些方法的使用,感興趣的朋友來(lái)看看吧<BR>
    2022-04-04
  • C++回調(diào)函數(shù)實(shí)現(xiàn)計(jì)算器和qsort

    C++回調(diào)函數(shù)實(shí)現(xiàn)計(jì)算器和qsort

    這篇文章主要介紹了C++回調(diào)函數(shù)實(shí)現(xiàn)計(jì)算器和qsort,回調(diào)函數(shù)就是一個(gè)通過(guò)函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來(lái)調(diào)用其所指向的函數(shù)時(shí),我們就說(shuō)這是回調(diào)函數(shù)
    2022-08-08
  • C語(yǔ)言實(shí)現(xiàn)航班管理系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)航班管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)航班管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單鏈表操作詳解

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單鏈表操作詳解

    鏈表是一種物理存儲(chǔ)結(jié)構(gòu)上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表中的指針鏈接次序?qū)崿F(xiàn)的。本文將和大家一起聊聊C語(yǔ)言中單鏈表的常用操作,感興趣的可以學(xué)習(xí)一下
    2022-07-07
  • C和C++的區(qū)別詳解

    C和C++的區(qū)別詳解

    這篇文章主要介紹了C和C++之間的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的結(jié)構(gòu)體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • c++連接mysql數(shù)據(jù)庫(kù)的兩種方法(ADO連接和mysql api連接)

    c++連接mysql數(shù)據(jù)庫(kù)的兩種方法(ADO連接和mysql api連接)

    現(xiàn)在正做一個(gè)接口,通過(guò)不同的連接字符串操作不同的數(shù)據(jù)庫(kù)。要用到mysql數(shù)據(jù)庫(kù),C++連接mysql有2種方法:利用ADO連接、利用mysql自己的api函數(shù)進(jìn)行連接,下面看看如何用吧
    2013-12-12
  • QT實(shí)現(xiàn)簡(jiǎn)單時(shí)鐘效果

    QT實(shí)現(xiàn)簡(jiǎn)單時(shí)鐘效果

    這篇文章主要為大家詳細(xì)介紹了QT實(shí)現(xiàn)簡(jiǎn)單時(shí)鐘效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • c++ 移動(dòng)構(gòu)造相關(guān)總結(jié)

    c++ 移動(dòng)構(gòu)造相關(guān)總結(jié)

    這篇文章主要介紹了c++ 移動(dòng)構(gòu)造的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用c++,感興趣的朋友可以了解下
    2021-02-02
  • c語(yǔ)言如何實(shí)現(xiàn)DES加密解密

    c語(yǔ)言如何實(shí)現(xiàn)DES加密解密

    這篇文章主要介紹了c語(yǔ)言如何實(shí)現(xiàn)DES加密解密問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04

最新評(píng)論

朝阳市| 陇南市| 嘉兴市| 泾阳县| 无极县| 喜德县| 遂昌县| 大邑县| 彩票| 蕉岭县| 商河县| 长乐市| 石阡县| 北安市| 三门县| 随州市| 仁怀市| 湖南省| 平乐县| 来安县| 宿州市| 辽宁省| 玉龙| 邢台市| 栾城县| 武威市| 宁南县| 汝城县| 巴彦淖尔市| 贵阳市| 河南省| 顺昌县| 泰来县| 建昌县| 新密市| 天水市| 福贡县| 新营市| 南靖县| 探索| 晋中市|