欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++11中的智能指針和垃圾回收使用

 更新時間:2023年02月02日 10:01:06   作者:Shawn-Summer  
本文主要介紹了C++11中的智能指針和垃圾回收使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在C/C++中,我們需要自己管理動態(tài)內(nèi)存區(qū),我們在寫代碼中可能會出現(xiàn)如下3中內(nèi)存管理的缺陷

  • 野指針:內(nèi)存單元已經(jīng)釋放,但是指向它的指針還在使用
  • 重復(fù)釋放:試圖是釋放已經(jīng)釋放過的內(nèi)存單元
  • 內(nèi)存泄漏:不再使用的內(nèi)存單元沒有進(jìn)行釋放

C++惡心的地方就在于它存在指針,需要編寫者自己管理內(nèi)存,所以內(nèi)存上面的問題就會有很多,但是在其他語言,例如python,java,C#,他都不存在指針概念,也就意味著你不需要開辟釋放內(nèi)存這些操作。而正因?yàn)镃++將指針暴露出來,甚至將右值引用暴露出來,才使得C++的運(yùn)行效率非???。

為了減少C++中的內(nèi)存問題,就出現(xiàn)了智能指針,它是一種對C風(fēng)格指針的優(yōu)化,它把內(nèi)存的釋放放在了智能指針的析構(gòu)函數(shù)中,這樣子就能減少一部分自己手動釋放內(nèi)存的代碼。

1.C++11中的unique_ptr

#include<memory>
#include<iostream>
using namespace std;
int main()
{
? ? unique_ptr<int> up1(new int(11));
? ? unique_ptr<int> up2=up1;//無法通過編譯

? ? cout<<*up1<<endl;//11
? ? unique_ptr<int> up3=move(up1);//現(xiàn)在up3是數(shù)據(jù)的唯一指針

? ? cout<<*up3<<endl;//11
? ? cout<<*up1<<endl;//運(yùn)行錯誤

? ? up3.reset();//釋放內(nèi)存
? ? up1.reset();//不會重復(fù)釋放內(nèi)存

? ? cout<<*up3<<endl;//運(yùn)行錯誤
}

我們知道unique_ptr正如它的名字一樣,它表示一個對象只能由一個指針綁定,不允許一個對象同時又多個unique_ptr綁定。

而且 unique_ptr只存在移動語義,而不存在拷貝語義 ,我們看上面代碼中unique_ptr<int> up3=move(up1);,在unique_ptr中只存在移動構(gòu)造函數(shù)和移動賦值函數(shù),不存在拷貝構(gòu)造函數(shù)和拷貝賦值函數(shù)。所以說我們只能用右值來構(gòu)造或賦值unique_ptr。

還有一種初始化unique_ptr的方法就是:make_unique<>(),相較于使用new初始化,前者內(nèi)存碎片化更少,在現(xiàn)代C++種主要使用,make_unique。

實(shí)際上,C++98中的auto_ptr和C++11中的unique_ptr實(shí)現(xiàn)的是同一個東西,但是在C++98中我們不存在移動語義,所以auto_ptr它是存在拷貝構(gòu)造函數(shù)和拷貝賦值函數(shù)的,所以諸如:
auto_ptr<int> up2=up1;是可以通過編譯的,在C++11中我們廢棄掉了,auto_ptr也是這個原因。

2.C++11中的shared_ptr和weak_ptr

shared_ptr是一種共享式的指針,它采用引用計(jì)數(shù)的方式,來決定何時釋放內(nèi)存,引用計(jì)數(shù)就是說,它統(tǒng)計(jì)每個對象有幾個指針指向它。一旦一個對象的引用計(jì)數(shù)為0,即不存在指向它的指針,那么就釋放它。
weak_ptr是用來驗(yàn)證shared_ptr指向的內(nèi)存單元的有效性的,被它指向的對象的引用計(jì)數(shù)不會增加。

#include<memory>
#include<iostream>
using namespace std;

void Check(weak_ptr<int>& wp)
{
? ? shared_ptr<int> sp=wp.lock();
? ? if(sp!=nullptr)
? ? ? ? cout<<"still "<<*sp<<endl;
? ? else
? ? ? ? cout<<"pointer is invalid."<<endl;
}
int main()
{
? ? shared_ptr<int> sp1=make_shared<int>(22);
? ? shared_ptr<int> sp2=sp1;
? ? weak_ptr<int> wp=sp1;

? ? cout<<*sp1<<endl;
? ? cout<<*sp2<<endl;
? ? Check(wp);

? ? sp1.reset();
? ? cout<<*sp2<<endl;
? ? Check(wp);

? ? sp2.reset();
? ? Check(wp);

}

22
22
still 22
22
still 22
pointer is invalid.

3.垃圾回收

雖然智能指針能夠幫助用戶有效管理堆內(nèi)存,但是它還是需要顯式聲明智能指針,而完全不需要指針的內(nèi)存管理方法也會更討人喜歡。這種方法就是垃圾回收機(jī)制,寫代碼的時候不需要開辟釋放內(nèi)存操作,這些操作都由編譯器自動實(shí)現(xiàn),這種智能化的方案就是垃圾回收機(jī)制。

遺憾的是,C++不支持垃圾回收機(jī)制。

垃圾回收的方式有4種

基于引用計(jì)數(shù)的方法
其實(shí)就是和shared_ptr一樣的方式,就是一旦對象的引用次數(shù)為0就釋放它,python就是使用的這種方案,不過這種方案不好,它效率比較低,一旦對象創(chuàng)建,或者有指針指向它,都要計(jì)算引用此時,而且它不能解決"環(huán)形引用"問題

標(biāo)記-清除
這種方法就是存在一個根對象,它管理所有對象,依次遍歷每個對象,給它們引用的區(qū)域打上標(biāo)記,然后遍歷完成后,把所有沒有標(biāo)記的區(qū)域釋放掉,這種方案的缺陷在于會存在大量的內(nèi)存碎片

標(biāo)記-整理
它是在標(biāo)記-清除方案的基礎(chǔ)上,標(biāo)記完后不再遍歷釋放垃圾了,而是所有被標(biāo)記的區(qū)域,向左靠齊,這樣就減少了內(nèi)存碎片

標(biāo)記-拷貝
它是將內(nèi)存空間分為兩塊:From和to,剛開始就從From空間種分配內(nèi)存,一旦From內(nèi)存滿了,就把From空間中所有活對象,拷貝到to空間中,而且都是向左靠齊的,然后再將From和to的角色互換。

很遺憾C++11目前還沒有公開支持過垃圾回收,不過有些庫和有限編譯器支持了部分垃圾回收的功能

int main()
{
? ? int *p=new int;
? ? p+=10;
? ? p-=10;
? ? *p=10;
}

上面代碼中,一旦p指向了其他區(qū)域,如果你的編譯器支持垃圾回收,例如采用的引用計(jì)時方式,那么一旦p移到了其他地區(qū),這個開辟的new int空間,就會被釋放,更危險的是,這塊空間會被其他線程使用,這時候,p如果又指回了原來的地方,那么p就是一個野指針。

為了防止,new int這塊空間被垃圾回收器回收掉,我們的一種方案是:

int main()
{
    int *p=new int;
    declare_reachable(p);
    p+=10;
    p-=10;
    *p=10;
}

這里的declare_reachable函數(shù)顯式的告訴垃圾回收器,你不要取釋放這塊空間

到此這篇關(guān)于C++11中的智能指針和垃圾回收使用的文章就介紹到這了,更多相關(guān)C++11 智能指針和垃圾回收內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Qt+opencv開發(fā)的視頻播放器示例詳解

    基于Qt+opencv開發(fā)的視頻播放器示例詳解

    這篇文章主要為大家介紹了基于Qt+opencv開發(fā)的視頻播放器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • C++中for auto的用法及說明

    C++中for auto的用法及說明

    這篇文章主要介紹了C++中for auto的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C++實(shí)現(xiàn)簡易通訊錄

    C++實(shí)現(xiàn)簡易通訊錄

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡易通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • 簡單分析C語言中指針數(shù)組與數(shù)組指針的區(qū)別

    簡單分析C語言中指針數(shù)組與數(shù)組指針的區(qū)別

    這篇文章主要介紹了C語言中指針數(shù)組與數(shù)組指針的區(qū)別,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • C++數(shù)據(jù)結(jié)構(gòu)哈希表詳解

    C++數(shù)據(jù)結(jié)構(gòu)哈希表詳解

    C++標(biāo)準(zhǔn)庫中使用的unordered_map底層實(shí)現(xiàn)是哈希表,下面這篇文章主要給大家介紹了關(guān)于C++中使用哈希表(unordered_map)的一些常用操作方法,需要的朋友可以參考下
    2022-07-07
  • c/c++中struct定義、聲明、對齊方式解析

    c/c++中struct定義、聲明、對齊方式解析

    這篇文章通過C/C++的兩種聲明方式開始,給大家詳細(xì)分析了/c+中struct定義、聲明、對齊方式,對此有興趣的朋友可以參考學(xué)習(xí)下。
    2018-03-03
  • C++11的新特性簡單匯總介紹 (二)

    C++11的新特性簡單匯總介紹 (二)

    最近學(xué)習(xí)了C++11的新特性,將學(xué)習(xí)內(nèi)容整理下來以鞏固記憶,這里分享給大家,希望對大家學(xué)習(xí)C++11能夠有所幫助
    2016-07-07
  • C++中實(shí)現(xiàn)OpenCV圖像分割與分水嶺算法

    C++中實(shí)現(xiàn)OpenCV圖像分割與分水嶺算法

    分水嶺算法是一種常用的圖像區(qū)域分割法,本文主要介紹了OpenCV圖像分割與分水嶺算法,使用C++實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2021-06-06
  • C語言函數(shù)棧幀的創(chuàng)建與銷毀原理圖解

    C語言函數(shù)棧幀的創(chuàng)建與銷毀原理圖解

    我們知道c語言中函數(shù)都是被調(diào)用的,main函數(shù)里面能調(diào)用其他函數(shù),其實(shí)main函數(shù)也是被別的函數(shù)調(diào)用的,下面通過本文給大家分享c語言函數(shù)棧幀的創(chuàng)建和銷毀過程,一起看看吧
    2022-05-05
  • 詳解C++?functional庫中的仿函數(shù)使用方法

    詳解C++?functional庫中的仿函數(shù)使用方法

    仿函數(shù)(functor)又稱之為函數(shù)對象(function?object),實(shí)際上就是?重載了()操作符?的?struct或class。本文將詳細(xì)講解C++中仿函數(shù)的使用方法,需要的可以參考一下
    2022-04-04

最新評論