1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      C++智能指針shared_ptr與右值如何引用

      這篇文章主要介紹“C++智能指針shared_ptr與右值如何引用”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“C++智能指針shared_ptr與右值如何引用”文章能幫助大家解決問題。

      10年積累的網(wǎng)站建設(shè)、網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認識你,你也不認識我。但先網(wǎng)站策劃后付款的網(wǎng)站建設(shè)流程,更有長樂免費網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

        1. 介紹

        在 C++ 中沒有垃圾回收機制,必須自己釋放分配的內(nèi)存,否則就會造成內(nèi)存泄露。解決這個問題最有效的方法是使用智能指針(smart pointer)。智能指針是存儲指向動態(tài)分配(堆)對象指針的類,用于生存期的控制,能夠確保在離開指針所在作用域時,自動地銷毀動態(tài)分配的對象,防止內(nèi)存泄露。智能指針的核心實現(xiàn)技術(shù)是引用計數(shù),每使用它一次,內(nèi)部引用計數(shù)加1,每析構(gòu)一次內(nèi)部的引用計數(shù)減1,減為0時,刪除所指向的堆內(nèi)存。

        C++11 中提供了三種智能指針,使用這些智能指針時需要引用頭文件:

        • std::shared_ptr:共享的智能指針

        • std::unique_ptr:獨占的智能指針

        • std::weak_ptr:弱引用的智能指針,它不共享指針,不能操作資源,是用來監(jiān)視 shared_ptr 的。

        共享智能指針(shared_ptr)是指多個智能指針可以同時管理同一塊有效的內(nèi)存,共享智能指針 shared_ptr 是一個模板類,如果要進行初始化有三種方式:通過構(gòu)造函數(shù)、std::make_shared 輔助函數(shù)以及 reset 方法。共享智能指針對象初始化完畢之后就指向了要管理的那塊堆內(nèi)存,如果想要查看當前有多少個智能指針同時管理著這塊內(nèi)存可以使用共享智能指針提供的一個成員函數(shù) use_count

        2. 初始化方法

        2.1 通過構(gòu)造函數(shù)初始化

        實例

        // 使用智能指針管理一塊 int 型的堆內(nèi)存
        shared_ptr ptr1(new int(520));

        2.2 通過拷貝和移動構(gòu)造函數(shù)初始化

        調(diào)用拷貝構(gòu)造函數(shù)

        shared_ptr ptr2(ptr1);

        調(diào)用移動構(gòu)造函數(shù)

        std::shared_ptr ptr5 = std::move(ptr2);

        如果使用拷貝的方式初始化共享智能指針對象,這兩個對象會同時管理同一塊堆內(nèi)存,堆內(nèi)存對應(yīng)的引用計數(shù)也會增加;
        如果使用移動的方式初始智能指針對象,只是轉(zhuǎn)讓了內(nèi)存的所有權(quán),管理內(nèi)存的對象并不會增加,因此內(nèi)存的引用計數(shù)不會變化。

        2.2.1 移動構(gòu)造

        關(guān)于移動構(gòu)造,可能有些讀者不太明白

        移動構(gòu)造是C++11標準中提供的一種新的構(gòu)造方法。

        在現(xiàn)實中有很多這樣的例子,我們將錢從一個賬號轉(zhuǎn)移到另一個賬號,將手機SIM卡轉(zhuǎn)移到另一臺手機,將文件從一個位置剪切到另一個位置……移動構(gòu)造可以減少不必要的復(fù)制,帶來性能上的提升。

        我們首先來看看move函數(shù)
        首先看這樣一段代碼

        #include 
        #include 
        #include 
        #include 
        
        using namespace std;
        
        int main()
        {
        	string st = "I love 進擊的汪sir";
        	vector vc;
        	vc.push_back(move(st));
        	cout << vc[0] << endl;
        	if (!st.empty())
        		cout << st << endl;
        
        	return 0;
        }

        輸出的結(jié)果為

        C++智能指針shared_ptr與右值如何引用

        再看這樣一段代碼

        #include 
        #include 
        #include 
        #include 
        
        using namespace std;
        
        int main()
        {
        	string st = "I love xing";
        	vector vc;
        	vc.push_back(st);
        	cout << vc[0] << endl;
        	if (!st.empty())
        		cout << st << endl;
        
        	return 0;
        }

        其結(jié)果為

        C++智能指針shared_ptr與右值如何引用

        這兩段代碼唯一的不同是調(diào)用vc.push_back()將字符串插入到容器中去時,第一段代碼使用了move語句,而第二段代碼沒有使用move語句。輸出的結(jié)果差異也很明顯,第一段代碼中,原來的字符串st已經(jīng)為空,而第二段代碼中,原來的字符串st的內(nèi)容沒有變化。

        先暫時記住這兩端代碼的輸出結(jié)果之間的差異。
        我們回到移動構(gòu)造函數(shù)上

        有時候我們會遇到這樣一種情況,我們用對象a初始化對象b,后對象a我們就不在使用了,但是對象a的空間還在呀(在析構(gòu)之前),既然拷貝構(gòu)造函數(shù),實際上就是把a對象的內(nèi)容復(fù)制一份到b中,那么為什么我們不能直接使用a的空間呢?這樣就避免了新的空間的分配,大大降低了構(gòu)造的成本。這就是移動構(gòu)造函數(shù)設(shè)計的初衷。

        通俗一點的解釋就是,拷貝構(gòu)造函數(shù)中,對于指針,我們一定要采用深層復(fù)制,而移動構(gòu)造函數(shù)中,對于指針,我們采用淺層復(fù)制。

        所以在上面的例子中,如果調(diào)用移動構(gòu)造函數(shù)來初始化智能指針,引用計數(shù)是不會增加的,而move函數(shù)實際上是返回的右值引用

        2.2.2 右值引用

        上面我們講到了右值引用,這里就來擴展一下右值引用是啥
        首先得分清楚,什么是右值,什么是左值

        • lvalue 是 loactor value 的縮寫,rvalue 是 read value 的縮寫

        • 左值是指存儲在內(nèi)存中、有明確存儲地址(可取地址)的數(shù)據(jù);

        • 右值是指可以提供數(shù)據(jù)值的數(shù)據(jù)(不可取地址);

        通過描述可以看出,區(qū)分左值與右值的便捷方法是:可以對表達式取地址(&)就是左值,否則為右值 。所有有名字的變量或?qū)ο蠖际亲笾担抑凳悄涿摹?/p>

        C++11 中右值可以分為兩種:一個是將亡值( xvalue, expiring value),另一個則是純右值( prvalue, PureRvalue):

        • 純右值:非引用返回的臨時變量、運算表達式產(chǎn)生的臨時變量、原始字面量和 lambda 表達式等

        • 將亡值:與右值引用相關(guān)的表達式,比如,T&& 類型函數(shù)的返回值、 std::move 的返回值等。

        右值引用就是對一個右值進行引用的類型。因為右值是匿名的,所以我們只能通過引用的方式找到它。無論聲明左值引用還是右值引用都必須立即進行初始化,因為引用類型本身并不擁有所綁定對象的內(nèi)存,只是該對象的一個別名。通過右值引用的聲明,該右值又“重獲新生”,其生命周期與右值引用類型變量的生命周期一樣,只要該變量還活著,該右值臨時量將會一直存活下去。

        右值通過&&來引用

        例如:

        • int&& value = 520; 里面 520 是純右值,value 是對字面量 520 這個右值的引用。

        • int &&a2 = a1; 中 a1 雖然寫在了 = 右邊,但是它仍然是一個左值,使用左值初始化一個右值引用類型是不合法的。

        • const Test& t = getObj() 這句代碼的語法是正確的,常量左值引用是一個萬能引用類型,它可以接受左值、右值、常量左值和常量右值。

        2.3 通過 std::make_shared 初始化

        通過 C++ 提供的 std::make_shared() 就可以完成內(nèi)存對象的創(chuàng)建并將其初始化給智能指針,函數(shù)原型如下:

        template< class T, class... Args >
        shared_ptr make_shared( Args&&... args );

        實例
        使用智能指針管理一塊 int 型的堆內(nèi)存, 內(nèi)部引用計數(shù)為 1

        shared_ptr ptr1 = make_shared(520);

        注意
        使用 std::make_shared() 模板函數(shù)可以完成內(nèi)存地址的創(chuàng)建,并將最終得到的內(nèi)存地址傳遞給共享智能指針對象管理。如果申請的內(nèi)存是普通類型,通過函數(shù)的()可完成地址的初始化,如果要創(chuàng)建一個類對象,函數(shù)的()內(nèi)部需要指定構(gòu)造對象需要的參數(shù),也就是類構(gòu)造函數(shù)的參數(shù)。

        2.4 通過 reset 方法初始化

        共享智能指針類提供的 std::shared_ptr::reset 方法函數(shù)原型如下:

        void reset() noexcept;
        
        template< class Y >
        void reset( Y* ptr );
        
        template< class Y, class Deleter >
        void reset( Y* ptr, Deleter d );
        
        template< class Y, class Deleter, class Alloc >
        void reset( Y* ptr, Deleter d, Alloc alloc );
        • ptr:指向要取得所有權(quán)的對象的指針

        • d:指向要取得所有權(quán)的對象的指針

        • aloc:內(nèi)部存儲所用的分配器

        實例

        shared_ptr ptr5;
        ptr5.reset(new int(250));

        3. 獲取原始指針

        對應(yīng)基礎(chǔ)數(shù)據(jù)類型來說,通過操作智能指針和操作智能指針管理的內(nèi)存效果是一樣的,可以直接完成數(shù)據(jù)的讀寫。但是如果共享智能指針管理的是一個對象,那么就需要取出原始內(nèi)存的地址再操作,可以調(diào)用共享智能指針類提供的 get () 方法得到原始地址,其函數(shù)原型如下:

        T* get() const noexcept;

        實例

        #include 
        #include 
        #include 
        using namespace std;
        
        int main()
        {
            int len = 128;
            shared_ptr ptr(new char[len]);
            // 得到指針的原始地址
            char* add = ptr.get();
            memset(add, 0, len);
            strcpy(add, "博客:進擊的汪sir");
            cout << "string: " << add << endl;
            
            shared_ptr p(new int);
            *p = 100;
            cout << *p.get() << "  " << *p << endl;
            
            return 0;
        }

        4. 指定刪除器

        當智能指針管理的內(nèi)存對應(yīng)的引用計數(shù)變?yōu)?0 的時候,這塊內(nèi)存就會被智能指針析構(gòu)掉了。另外,我們在初始化智能指針的時候也可以自己指定刪除動作,這個刪除操作對應(yīng)的函數(shù)被稱之為刪除器,這個刪除器函數(shù)本質(zhì)是一個回調(diào)函數(shù),我們只需要進行實現(xiàn),其調(diào)用是由智能指針完成的。

        實例

        #include 
        #include 
        using namespace std;
        
        // 自定義刪除器函數(shù),釋放int型內(nèi)存
        void deleteIntPtr(int* p)
        {
            delete p;
            cout << "int 型內(nèi)存被釋放了...";
        }
        
        int main()
        {
            shared_ptr ptr(new int(250), deleteIntPtr);
            return 0;
        }

        刪除器函數(shù)也可以是 lambda 表達式!

        關(guān)于“C++智能指針shared_ptr與右值如何引用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。


        本文題目:C++智能指針shared_ptr與右值如何引用
        分享地址:http://www.ef60e0e.cn/article/pesogj.html
        99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
        1. <ul id="0c1fb"></ul>

          <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
          <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

          松潘县| 石泉县| 出国| 南阳市| 甘孜| 黄山市| 晋城| 分宜县| 泾川县| 宣城市| 丹东市| 文昌市| 安顺市| 高阳县| 五华县| 娄底市| 黄大仙区| 三原县| 江都市| 攀枝花市| 新乡市| 黄石市| 阳城县| 通道| 剑川县| 田东县| 曲麻莱县| 南漳县| 永兴县| 阜平县| 平阳县| 金川县| 桂平市| 南丰县| 兰坪| 莱西市| 安福县| 安徽省| 通山县| 荆州市| 铅山县|