溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++內(nèi)存管理如何理解

發(fā)布時(shí)間:2022-01-06 12:55:09 來源:億速云 閱讀:157 作者:柒染 欄目:開發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)C++內(nèi)存管理如何理解,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

    前言;

    C++繼承了C語言的指針,一直以來指針的一些問題困擾著開發(fā)人員,常見的指針問題主要有:內(nèi)存泄露、野指針、訪問越界等。值得慶幸的是C++標(biāo)準(zhǔn)委員會給我們提供了auto_ptr智能指針,后面又引入了share_ptr以及weak_ptr幫助我們正確和安全的使用指針,下面主要是介紹boost庫提供的解決方案。

    1 smart_ptr概述

    在實(shí)際開發(fā)時(shí),我們會根據(jù)不同的編程場景申請不同的資源,對于這些資源的管理需要一個(gè)完善的方案,我們希望在資源釋放后,C++能夠像java,c#一樣不用去手動的釋放資源而是由系統(tǒng)自動對資源進(jìn)行回收。

    1.1 RAII進(jìn)制

    C++編程時(shí)通常使用這種方法管理資源,申請的資源超過生命周期后,生命的對象自動調(diào)用析構(gòu)函數(shù)對資源進(jìn)行正確回收。如此看來,似乎是完美的解決我們的問題,至少在使用時(shí)不用手動釋放資源。但是這種資源釋放的方法同樣存在著缺陷,如果對象是在棧上創(chuàng)建得到,那么會自動調(diào)用析構(gòu)函數(shù),結(jié)果也是沒有問題的,但是如果對象是通過new在堆上創(chuàng)建的呢?結(jié)果是析構(gòu)函數(shù)不能自動被調(diào)用,同樣需要我們使用delete進(jìn)行顯示析構(gòu)。如果程序在執(zhí)行時(shí)沒有調(diào)用析構(gòu)delete進(jìn)行釋放資源,那么同樣也會存在內(nèi)存泄露的風(fēng)險(xiǎn)。

    new/delete在編程時(shí)一定要遵循配對原則,且要服從誰創(chuàng)建誰釋放的規(guī)則,這一點(diǎn)不管是新手程序員還是有著豐富編程經(jīng)驗(yàn)的老手都要認(rèn)真對待。

    1.2 智能指針

    從C98開始,C++標(biāo)準(zhǔn)委員會就給我們提供了智能指針:auto_ptr。它部分解決了資源的自動釋放問題。

    使用方法如下:

    std::auto_ptr<int> p (new int);

    auto_ptr的構(gòu)造函數(shù)支持new操作符或者由對象工廠創(chuàng)建的對象指針作為參數(shù)。對象一經(jīng)創(chuàng)建就托管了原始指針,因此它可以使用get方法返回指針對象,如:

    *p.get() = 100;

    auto_ptr受到了大家的歡迎,越來越多的人使用這種技術(shù)解決了實(shí)際編程中大部分得到資源管理的問題,但是,auto_ptr并不是一種非常完善的技術(shù),也沒有覆蓋到智能指針的所有領(lǐng)域,尤其是引用計(jì)數(shù)型的智能指針。同理,在使用auto_ptr的時(shí)候也要注意以下幾點(diǎn),避免auto_ptr的濫用。

    • auto_ptr不能共享所有權(quán),即不要讓兩個(gè)auto_ptr指向同一個(gè)對象。

    • auto_ptr不能指向數(shù)組,因?yàn)?code>auto_ptr在析構(gòu)的時(shí)候只是調(diào)用delete。

    • auto_ptr只是一種簡單的智能指針,如有特殊需求,需要使用其他智能指針,比如share_ptr。

    • auto_ptr不能作為容器對象。

    為了解決auto_ptr的不足,boost庫提供了多種類之中從而完善了auto_ptr的不足。這些指針都在boost庫的頭文件中,

    如下所示:

    #include <boost/smart_ptr.hpp>
    using namespace boost;

    1.3 scoped_ptr

    該類型指針和auto_ptr類似,但是限制也更加嚴(yán)格,scoped_ptr對象一旦獲取對象的管理權(quán)就將一直占用,不能在進(jìn)行管理權(quán)轉(zhuǎn)移。scoped_ptr像它的名字一樣,只能在起作用域內(nèi)進(jìn)行使用。使用后會使得代碼相對簡單且不會增加多余操作。

    scoped_ptr使用方法:

    scoped_ptr使用簡單,只需要在原來使用new的地方用scoped_ptr進(jìn)行替換即可,

    使用方法如下:

    scoped_ptr<string> pStr(new string("hello word"));

    操作scoped_ptr指針也很簡單,使用方式和普通指針一致,如:

    //打印指針指向字符串內(nèi)容
    cout<<pAtr<<endl;
    //打印字符長度
    cout<<pAtr->size()<<endl;

    需要注意的是:1)此指針對象會進(jìn)行自動釋放,無需使用delete進(jìn)行釋放,如果在實(shí)際編程時(shí)使用了delete,編譯器將會報(bào)錯(cuò),大家不妨可以思考下原因是什么歡迎留言。2)scoped_ptr是不能進(jìn)行賦值、拷貝操作得到,生命周期只限于聲明的作用域內(nèi)。

    和auto_ptr指針相比,scoped_ptr的不同點(diǎn)如下:

    兩者都不能作為容器元素,但是原因卻不同。auto_ptr是因?yàn)樗陨淼霓D(zhuǎn)義語義,但是scoped_ptr是因?yàn)椴恢С挚截惡蛷?fù)制。

    指針?biāo)袡?quán)不同,auto_ptr是可以進(jìn)行轉(zhuǎn)義得到,但是scoped_ptr不能進(jìn)行轉(zhuǎn)義,因?yàn)槠錁?gòu)造和拷貝函數(shù)都是私有的。

    1.4 scoped_array

    scoped_arrayscoped_ptr基本相同,根本區(qū)別是scoped_array是指向數(shù)組的,封裝了new[],彌補(bǔ)了指向數(shù)組的智能指針。

    scoped_array使用方法:

    scoped_array和scoped_ptr設(shè)計(jì)思想相同,使用方法也基本一致,如下:

    scoped_array<int> pIntArray(new int[10]);

    使用時(shí)需要注意的是:scoped_array不會對數(shù)組范圍進(jìn)行檢查,且不能通過數(shù)組名+偏移的方式進(jìn)行獲取。

    但可以按照以下方式使用:

    pIntArray[0]=100;
    pIntArray[1]=200;
    1.5 shared_ptr

    shared_ptr已經(jīng)被引入C++標(biāo)準(zhǔn)庫中,功能強(qiáng)大,可以像普通指針那樣使用,它是引用計(jì)數(shù)型指針,可以被任意的復(fù)制和拷貝。同時(shí)shared_ptr可以被用作容器元素。

    可以說shared_ptr是C++歷史上實(shí)現(xiàn)智能指針?biāo)惴ㄖ凶罱艹龅拇碜鳌?/p>

     shared_ptr使用方法:

    shared_ptr指針是最接近原始指針的。他比auto_ptrscoped_ptr應(yīng)用范圍更廣,幾乎可以百分之百避免程序中的內(nèi)存泄露,但是使用卻又像auto_ptr和scoped_ptr一樣簡單。

    shared_ptr是線程安全的,可以由多個(gè)線程進(jìn)行讀取。

    使用方式如下:

    int main()
    {
        //定義一個(gè)指針對象
       shared_ptr<int> pInt(new int);
       //對指針進(jìn)行賦值
       *pInt = 100;
       cout<<*pInt<<endl;
       //調(diào)用shared_ptr重載方法
       shared_ptr<int> pInt_cp = pInt;
       cout<<*pInt_cp<<endl;
       pInt.reset();
       assert(!pInt);
       return 0;
    }

    如上代碼所示shared_ptr構(gòu)造函數(shù)中依舊使用new的方法創(chuàng)建一個(gè)對象,但這個(gè)遠(yuǎn)遠(yuǎn)不夠,shared_ptr提供make_shared方法來創(chuàng)建一個(gè)共享指針對象,

    方式如下:

    int main()
    {
       shared_ptr<string> pStr= make_shared<string>("hello world");
       cout<<*pStr<<endl;
       shared_ptr<vector<int> > pVec = make_shared<vector<int> >(10,2);
       cout<<pVec->size()<<endl;
       return 0;
    }

    代碼輸出結(jié)果為:

    hello world
    10

    shared_ptr高級用法;

    shared_ptr 可以保存任意類型指針,可以理解成是改指針是泛型的。

    shared_ptr<void *>退出作用域后調(diào)用回調(diào)函數(shù),如下:

    void fun(void *p){}
    shared_ptr<void *> p((void *0),fun);

    除此之外,shared_ptr還有其它很多高級用法,如:延時(shí)釋放、包裝成員函數(shù)等,感興趣的話可以自行研究。

    1.6 shared_array

    shared_array功能和shared_ptr類似,根本區(qū)別是包裝了new[]操作符,可以指向數(shù)組,知道引用計(jì)數(shù)為0時(shí)才會進(jìn)行釋放。

     shared_array使用方法:

    shared_arrayshared_ptrscoped_array的結(jié)合體。

    使用方法如下所示:

    int main()
    {
       int *p = new int[100];
       shared_array<int> sp(p);
       shared_array<int> sp1=sp;
       sp[0]=10;
       return 0;
    }

    1.7 weak_ptr弱指針

    weak_ptr不具備普通指針的行為,需要和shared_ptr配合使用。主要用于協(xié)助shared_ptr工作,觀測資源的使用情況。

     weak_ptr使用方法:

    weak_ptrshared_ptr共用可以通過shared_ptr或者weak_ptr對象構(gòu)造,使用時(shí)不會產(chǎn)生引用計(jì)數(shù)增加,析構(gòu)時(shí)也不會導(dǎo)致引用計(jì)數(shù)的減少??梢允褂胾se_count查看引用計(jì)數(shù),也可以使用其等效的方法expired(),如果引用計(jì)數(shù)為0則表示觀測的對已經(jīng)不存在了。代碼示例如下:

    int main()
    {
       shared_ptr<int> p(new int(100));
       cout<<p.use_count()<<endl;
       weak_ptr<int> wp(p);
       cout<<wp.use_count()<<endl;
       p.reset();
       if(!wp.expired())
       {
           shared_ptr<int> p1=wp.lock();
           *p1 = 1000;
           cout<<wp.use_count()<<endl;
       }
       return 0;
    }

    上述就是小編為大家分享的C++內(nèi)存管理如何理解了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    c++
    AI