亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

淺談 C++ 中的 new/delete 和 new[]/delete[]

2019-11-06 06:11:14
字體:
來源:轉載
供稿:網友

原始出處:http://www.cnblogs.com/hazir/p/new_and_delete.html

在 C++ 中,你也許經常使用 new 和 delete 來動態申請和釋放內存,但你可曾想過以下問題呢?

new 和 delete 是函數嗎?new [] 和 delete [] 又是什么?什么時候用它們?你知道 Operator new 和 operator delete 嗎?為什么 new [] 出來的數組有時可以用 delete 釋放有時又不行?…

如果你對這些問題都有疑問的話,不妨看看我這篇文章。

new 和 delete 到底是什么?

如果找工作的同學看一些面試的書,我相信都會遇到這樣的題:sizeof 不是函數,然后舉出一堆的理由來證明 sizeof 不是函數。在這里,和 sizeof 類似,new 和 delete 也不是函數,它們都是 C++ 定義的關鍵字,通過特定的語法可以組成表達式。和 sizeof 不同的是,sizeof 在編譯時候就可以確定其返回值,new 和 delete 背后的機制則比較復雜。繼續往下之前,請你想想你認為 new 應該要做些什么?也許你第一反應是,new 不就和 C 語言中的 malloc 函數一樣嘛,就用來動態申請空間的。你答對了一半,看看下面語句:

string *ps = new string("hello world");

你就可以看出 new 和 malloc 還是有點不同的,malloc 申請完空間之后不會對內存進行必要的初始化,而 new 可以。所以 new exPRession 背后要做的事情不是你想象的那么簡單。在我用實例來解釋 new 背后的機制之前,你需要知道 operator new 和 operator delete 是什么玩意。

operator new 和 operator delete

這兩個其實是 C++ 語言標準庫的庫函數,原型分別如下:

void *operator new(size_t);     //allocate an objectvoid *operator delete(void *);    //free an objectvoid *operator new[](size_t);     //allocate an arrayvoid *operator delete[](void *);    //free an array

后面兩個你可以先不看,后面再介紹。前面兩個均是 C++ 標準庫函數,你可能會覺得這是函數嗎?請不要懷疑,這就是函數!C++ Primer 一書上說這不是重載 new 和 delete 表達式(如 operator= 就是重載 = 操作符),因為 new 和 delete 是不允許重載的。但我還沒搞清楚為什么要用 operator new 和 operator delete 來命名,比較費解。我們只要知道它們的意思就可以了,這兩個函數和 C 語言中的 malloc 和 free 函數有點像了,都是用來申請和釋放內存的,并且 operator new 申請內存之后不對內存進行初始化,直接返回申請內存的指針。

我們可以直接在我們的程序中使用這幾個函數。

new 和 delete 背后機制

知道上面兩個函數之后,我們用一個實例來解釋 new 和 delete 背后的機制:

我們不用簡單的 C++ 內置類型來舉例,使用復雜一點的類類型,定義一個類 A:

class A{public:    A(int v) : var(v)    {        fopen_s(&file, "test", "r");    }    ~A()    {        fclose(file);    }private:    int var;    FILE *file;};

很簡單,類 A 中有兩個私有成員,有一個構造函數和一個析構函數,構造函數中初始化私有變量 var 以及打開一個文件,析構函數關閉打開的文件。

我們使用

class A *pA = new A(10);

來創建一個類的對象,返回其指針 pA。如下圖所示 new 背后完成的工作:

簡單總結一下:

首先需要調用上面提到的 operator new 標準庫函數,傳入的參數為 class A 的大小,這里為 8 個字節,至于為什么是 8 個字節,你可以看看《深入 C++ 對象模型》一書,這里不做多解釋。這樣函數返回的是分配內存的起始地址,這里假設是 0x007da290。上面分配的內存是未初始化的,也是未類型化的,第二步就在這一塊原始的內存上對類對象進行初始化,調用的是相應的構造函數,這里是調用 A:A(10); 這個函數,從圖中也可以看到對這塊申請的內存進行了初始化,var=10, file 指向打開的文件。最后一步就是返回新分配并構造好的對象的指針,這里 pA 就指向 0x007da290 這塊內存,pA 的類型為類 A 對象的指針。

所有這三步,你都可以通過反匯編找到相應的匯編代碼,在這里我就不列出了。

好了,那么 delete 都干了什么呢?還是接著上面的例子,如果這時想釋放掉申請的類的對象怎么辦?當然我們可以使用下面的語句來完成:

delete pA;

delete 所做的事情如下圖所示:

delete 就做了兩件事情:

調用 pA 指向對象的析構函數,對打開的文件進行關閉。通過上面提到的標準庫函數 operator delete 來釋放該對象的內存,傳入函數的參數為 pA 的值,也就是 0x007d290。

好了,解釋完了 new 和 delete 背后所做的事情了,是不是覺得也很簡單?不就多了一個構造函數和析構函數的調用嘛。

如何申請和釋放一個數組?

我們經常要用到動態分配一個數組,也許是這樣的:

string *psa = new string[10];      //array of 10 empty stringsint *pia = new int[10];           //array of 10 uninitialized ints

上面在申請一個數組時都用到了 new [] 這個表達式來完成,按照我們上面講到的 new 和 delete 知識,第一個數組是 string 類型,分配了保存對象的內存空間之后,將調用 string 類型的默認構造函數依次初始化數組中每個元素;第二個是申請具有內置類型的數組,分配了存儲 10 個 int 對象的內存空間,但并沒有初始化。

如果我們想釋放空間了,可以用下面兩條語句:

delete [] psa;delete [] pia;

都用到 delete [] 表達式,注意這地方的 [] 一般情況下不能漏掉!我們也可以想象這兩個語句分別干了什么:第一個對 10 個 string 對象分別調用析構函數,然后再釋放掉為對象分配的所有內存空間;第二個因為是內置類型不存在析構函數,直接釋放為 10 個 int 型分配的所有內存空間。

這里對于第一種情況就有一個問題了:我們如何知道 psa 指向對象的數組的大?。吭趺粗勒{用幾次析構函數?

這個問題直接導致我們需要在 new [] 一個對象數組時,需要保存數組的維度,C++ 的做法是在分配數組空間時多分配了 4 個字節的大小,專門保存數組的大小,在 delete [] 時就可以取出這個保存的數,就知道了需要調用析構函數多少次了。

還是用圖來說明比較清楚,我們定義了一個類 A,但不具體描述類的內容,這個類中有顯示的構造函數、析構函數等。那么 當我們調用

class A *pAa = new A[3];

時需要做的事情如下:

從這個圖中我們可以看到申請時在數組對象的上面還多分配了 4 個字節用來保存數組的大小,但是最終返回的是對象數組的指針,而不是所有分配空間的起始地址。

這樣的話,釋放就很簡單了:

delete []pAa;

這里要注意的兩點是:

調用析構函數的次數是從數組對象指針前面的 4 個字節中取出;傳入 operator delete[] 函數的參數不是數組對象的指針 pAa,而是 pAa 的值減 4。

為什么 new/delete 、new []/delete[] 要配對使用?

其實說了這么多,還沒到我寫這篇文章的最原始意圖。從上面解釋的你應該懂了 new/delete、new[]/delete[] 的工作原理了,因為它們之間有差別,所以需要配對使用。但偏偏問題不是這么簡單,這也是我遇到的問題,如下這段代碼:

int *pia = new int[10];delete []pia;

這肯定是沒問題的,但如果把 delete []pia; 換成 delete pia; 的話,會出問題嗎?

這就涉及到上面一節沒提到的問題了。上面我提到了在 new [] 時多分配 4 個字節的緣由,因為析構時需要知道數組的大小,但如果不調用析構函數呢(如內置類型,這里的 int 數組)?我們在 new [] 時就沒必要多分配那 4 個字節, delete [] 時直接到第二步釋放為 int 數組分配的空間。如果這里使用 delete pia;那么將會調用 operator delete 函數,傳入的參數是分配給數組的起始地址,所做的事情就是釋放掉這塊內存空間。不存在問題的。

這里說的使用 new [] 用 delete 來釋放對象的提前是:對象的類型是內置類型或者是無自定義的析構函數的類類型!

我們看看如果是帶有自定義析構函數的類類型,用 new [] 來創建類對象數組,而用 delete 來釋放會發生什么?用上面的例子來說明:

class A *pAa = new class A[3];delete pAa;

那么 delete pAa; 做了兩件事:

調用一次 pAa 指向的對象的析構函數;調用 operator delete(pAa); 釋放內存。

顯然,這里只對數組的第一個類對象調用了析構函數,后面的兩個對象均沒調用析構函數,如果類對象中申請了大量的內存需要在析構函數中釋放,而你卻在銷毀數組對象時少調用了析構函數,這會造成內存泄漏。

上面的問題你如果說沒關系的話,那么第二點就是致命的了!直接釋放 pAa 指向的內存空間,這個總是會造成嚴重的段錯誤,程序必然會奔潰!因為分配的空間的起始地址是 pAa 指向的地方減去 4 個字節的地方。你應該傳入參數設為那個地址!

同理,你可以分析如果使用 new 來分配,用 delete [] 來釋放會出現什么問題?是不是總會導致程序錯誤?

總的來說,記住一點即可:new/delete、new[]/delete[] 要配套使用總是沒錯的!

參考資料:

C++ Primer 第四版


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧洲成人免费aa| 最新亚洲国产精品| 欧美在线一级va免费观看| 国产主播精品在线| 日韩av在线网址| 国产精品国产三级国产专播精品人| 91国产中文字幕| 欧美午夜精品在线| 日韩av在线高清| 久久国产精品久久久久久久久久| 日韩黄在线观看| 国内精品美女av在线播放| 黑人巨大精品欧美一区二区| 亚洲欧美日本伦理| 日韩精品有码在线观看| 成人免费在线视频网站| 2019中文字幕在线免费观看| 国内精品在线一区| 亚洲电影免费观看高清完整版在线| 亚洲电影免费观看高清| 黑人极品videos精品欧美裸| 国产在线精品一区免费香蕉| 成人精品久久一区二区三区| 亚洲成av人乱码色午夜| 国产精品久久久久久久久| 在线亚洲午夜片av大片| 韩国三级电影久久久久久| 国产精品亚洲综合天堂夜夜| 久久久久久国产精品美女| 欧美日韩国产第一页| 国产视频福利一区| 色老头一区二区三区在线观看| 久久国产精品影视| 亚洲欧美中文在线视频| 欧美国产中文字幕| 国产99在线|中文| 国产精品精品视频一区二区三区| 欧美午夜片欧美片在线观看| 97国产一区二区精品久久呦| 中文字幕精品—区二区| 欧美亚洲第一页| 中文字幕国产亚洲| 亚洲综合在线小说| 亚洲欧美一区二区精品久久久| 日韩美女免费观看| 91网站在线免费观看| 热久久99这里有精品| 欧美午夜片在线免费观看| 欧美激情精品久久久久久黑人| 在线视频欧美日韩精品| 欧美高清无遮挡| 欧美国产日韩一区二区三区| 亚洲天堂av综合网| 色yeye香蕉凹凸一区二区av| 国产亚洲精品一区二区| 国产v综合v亚洲欧美久久| 最近更新的2019中文字幕| 欧美激情精品久久久久久黑人| 全色精品综合影院| 91视频免费在线| 欧美黑人性猛交| 精品无码久久久久久国产| 日韩欧美一区二区在线| 在线精品高清中文字幕| 国产日韩欧美日韩| 91情侣偷在线精品国产| 亚洲成avwww人| 久久久国产在线视频| 日韩精品视频中文在线观看| 欧美激情视频在线观看| 国产精品稀缺呦系列在线| 97视频免费在线看| 亚洲国产精品久久久| 久久视频这里只有精品| 国产精品美女久久久免费| 国产成人精品一区二区三区| 亚洲级视频在线观看免费1级| 国产精品免费久久久| 国产亚洲欧美aaaa| 国产精品久久电影观看| 欧美日韩在线视频观看| 国产人妖伪娘一区91| 欧美亚洲在线视频| 色偷偷亚洲男人天堂| 久久精品中文字幕一区| 欧美香蕉大胸在线视频观看| 国产亚洲欧美日韩一区二区| 91免费精品国偷自产在线| 国内自拍欧美激情| 久久久精品2019中文字幕神马| 国产98色在线| 亚洲第一精品夜夜躁人人躁| 国产午夜精品理论片a级探花| 国产香蕉精品视频一区二区三区| 成人精品aaaa网站| 久久精品国产亚洲7777| 亚洲高清色综合| 色综合久久精品亚洲国产| 亚洲欧美国产日韩天堂区| 夜夜嗨av一区二区三区免费区| 亚洲二区中文字幕| 综合网日日天干夜夜久久| 福利一区福利二区微拍刺激| 久久激情视频免费观看| 成人自拍性视频| 97精品久久久中文字幕免费| 97视频免费看| 欧美在线观看视频| 亚洲永久免费观看| 欧美老少做受xxxx高潮| 亚洲天堂免费在线| 国产va免费精品高清在线| 欧美一区在线直播| 日韩av在线网页| 超碰精品一区二区三区乱码| 精品露脸国产偷人在视频| 97精品在线视频| 亚洲第一综合天堂另类专| 久久精品色欧美aⅴ一区二区| 亚洲精品日韩在线| 久久久视频免费观看| 亚洲a级在线观看| 亚洲丝袜在线视频| 高清欧美电影在线| 亚洲激情免费观看| 久久久久久com| 亚洲欧美在线一区二区| 成人免费看吃奶视频网站| 亚洲精品国产精品国自产在线| 国产精品一区二区久久久久| 福利视频导航一区| 久久777国产线看观看精品| 亚洲国产精品福利| 亚洲免费伊人电影在线观看av| 欧洲美女7788成人免费视频| 欧美大片大片在线播放| 国产精品久久国产精品99gif| 久久精品国产欧美激情| 久久91精品国产91久久久| www国产亚洲精品久久网站| 国产精品午夜一区二区欲梦| 国产极品精品在线观看| 97色在线视频| 91国内揄拍国内精品对白| 亚洲天堂男人天堂女人天堂| 国产精品av免费在线观看| 欧美精品videossex性护士| 成人av在线天堂| 精品国产91乱高清在线观看| 久久精品影视伊人网| 欧美影院成年免费版| 日韩视频免费大全中文字幕| 91精品久久久久久久久久另类| 欧美疯狂xxxx大交乱88av| 隔壁老王国产在线精品| 精品无人区乱码1区2区3区在线| 欧美日韩亚洲视频一区| 九色精品免费永久在线| 亚洲第一福利在线观看| 国产精品av网站| 美女黄色丝袜一区| 精品国产乱码久久久久久虫虫漫画| 2019中文字幕免费视频| 中文字幕国产亚洲2019|