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

你知道C++中new和delete為什么要匹配使用嗎

 更新時間:2023年01月10日 09:19:56   作者:叫我小秦就好了  
關于 new 和 delete 的使用相信大家并不陌生,可是為什么使用 new 的時候要用 delete,使用 new[] 的時候又要用 delete[]呢?本文就來和大家詳細說說

前言

關于 new 和 delete 的使用相信大家并不陌生,可是為什么使用 new 的時候要用 delete,使用 new[] 的時候又要用 delete[]。使用 delete 釋放 new[] 申請的內存又會發(fā)生什么?為什么有時不匹配不會報錯,有時又會報錯呢?本文將為大家解決這個疑惑。

string* strArray = new string[1002];
...
delete strArray;

這段代碼看起來似乎沒有問題,既使用了 new,又搭配了 delete。但這代碼的行為是未定義的,最好的情況是有部分數據沒有析構,但更可能的是程序直接崩潰。

new 和 delete 做了什么

當使用 new 動態(tài)生成對象時,有兩件事發(fā)生:

1.調用全局的 operator new 分配內存

2.調用該對象的構造函數,對分配的內存進行初始化

內置類型的構造函數在這時什么都不做,故編譯器不用調用

當使用 delete 時,同樣會發(fā)生兩件事:

1.針對這段內存會有一個(或多個)析構函數被調用

2.調用全局的 operator delete 釋放內存

delete 的問題在于:將要釋放的內存中有多少個對象?這將決定有多少個析構函數被調用。

這個問題可以轉化為:指針所指向的是單一對象還是對象數組?如果是對象數組,那么里面又有多少個對象?因此我們有必要記錄數組的大小,以便 delete 知道需要調用多少次析構函數。例如下圖:

當然這只是個例子,不同的編譯器可能會有不同的方案,此處我們假定 n 占用 4 字節(jié)。

內置類型

new 和 new []

int* num = new int;
int* arr = new int[1002];

因為內置類型的默認構造函數并不會做什么處理,所以上述代碼在調用完 ::operator new() / ::operator new[]() 后,不會調用構造函數。同樣,因為無需調用構造函數,也不用多開辟一塊空間存儲對象個數。

delete 和 delete [ ]

int* num = new int;
int* arr = new int[1002];
delete num;
delete[] arr;

對于內置類型的 delete 也是非常簡單,只是單純的調用 ::operator delete() / ::operator delete[]() 釋放內存。內置類型沒有開辟存儲對象個數的空間,也不需要析構函數處理。

自定義類型

new 和 new []

string* str1 = new string;
string* str2 = new string[1231];

上述代碼首先會調用 ::operator new() / ::operator new[]() 申請內存,然后再調用 string 的默認構造函數進行初始化工作。

對于 new:因為只有一個對象,最后直接構造該對象即可,不用記錄個數。

對于 new []:因為最后需要調用析構函數析構所有對象,所以需要記錄對象的個數(即使是使用 new [] 申請一個對象),于是就在內存開頭處 4 字節(jié)記錄對象的個數(一種可能的方案),然后返回實際開辟的內存 + 4 的位置。

delete 和 delete [ ]

string* str1 = new string;
string* str2 = new string[1231];
delete str1;
delete[] str2;

上述代碼首先會調用 string 的析構函數進行清理工作,然后再調用 ::operator delete() / ::operator delete[]() 釋放內存。

對于 delete:直接析構該位置對象,然后釋放即可。

對于 delete[]:首先會查看前面 4 字節(jié)存儲的個數,來決定調用析構函數的次數;然后再調用 ::operator delete[]() 釋放內存,實際上 ::operator delete[]() 釋放的是地址減 4 后的值。因為實際開辟的前面還有 4 個字節(jié),要是不修正的話直接釋放的話,程序就會崩潰,因為系統(tǒng)并沒記錄該地址。

問題

自定義類型為什么要匹配使用

1.使用 new 和 delete

開辟一個對象,釋放一個對象,沒有問題

2.使用 new[] 和 delete

開辟一組對象,調用 ::operator delete(),因為沒有對地址進行修正,釋放了非法地址,程序會崩潰

3.使用 new 和 delete[]

開始一個對象,調用 ::operator delete[](),此時仍會把前面 4 個字節(jié)當成個數調用析構函數(個數是不確定的),然后再釋放減 4 后的地址,同樣釋放了非法地址,導致程序崩潰

4.使用 new[] 和 delete[]

開辟一組對象,釋放一組對象,沒有問題

內置類型不匹配為什么不報錯

使用 new[] 和 delete 或者 使用 new 和 delete[]

因為對于內置類型,默認情況下不會調用構造函數和析構函數,也不用開辟空間存儲對象個數。

因此最后的地址也不需要修正,于是就不會發(fā)生報錯了。

疑惑

其實全局的 new 和 delete 最后調用的是 malloc 和 free,malloc 在開辟空間時,同樣會多開辟一塊空間用于存儲內存塊的信息(在 Linux 64 位環(huán)境下是 16 字節(jié))。

頭信息中有存儲內存的字節(jié)大小,所以 free 時可以知道要釋放的內存大小。

那么問題來了,如果說對于自定義類型 new[] 返回的地址是上圖 malloc 返回的地址,對于該地址調用全局 delete,再傳遞給 free 此時是可以正確釋放內存的,只是析構函數調用次數不正確。但實際上程序直接崩潰,也就是說此時 new[] 返回的地址應該是 malloc 返回的地址右移 4 字節(jié)的值。

對這段內存模型只是猜測,博主也是菜雞,希望有大佬可以指正一下。

到此這篇關于你知道C++中new和delete為什么要匹配使用嗎的文章就介紹到這了,更多相關C++ new delete內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言循環(huán)鏈表的原理與使用操作

    C語言循環(huán)鏈表的原理與使用操作

    無論是靜態(tài)鏈表還是動態(tài)鏈表,有時在解決具體問題時,需要我們對其結構進行稍微地調整。比如,可以把鏈表的兩頭連接,使其成為了一個環(huán)狀鏈表,通常稱為循環(huán)鏈表
    2022-05-05
  • 關于C語言指針賦值的問題詳解

    關于C語言指針賦值的問題詳解

    本篇文章是對C語言指針賦值的問題進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實現大數乘法算法代碼

    C++實現大數乘法算法代碼

    這篇文章主要介紹了C++實現大數乘法算法代碼的相關資料,需要的朋友可以參考下
    2015-03-03
  • C++實現通訊錄管理系統(tǒng)項目

    C++實現通訊錄管理系統(tǒng)項目

    這篇文章主要為大家詳細介紹了C++實現通訊錄管理系統(tǒng)項目,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言庫函數中qsort()的用法

    C語言庫函數中qsort()的用法

    大家好,本篇文章主要講的是C語言庫函數中qsort()的用法,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • sigsetjmp的用法總結

    sigsetjmp的用法總結

    sigsetjmp()會保存目前堆棧環(huán)境,然后將目前的地址作一個記號,而在程序其他地方調用siglongjmp()時便會直接跳到這個記號位置,然后還原堆棧,繼續(xù)程序的執(zhí)行
    2013-09-09
  • C++ 中l(wèi)ambda表達式的編譯器實現原理

    C++ 中l(wèi)ambda表達式的編譯器實現原理

    C++ 11加入了一個非常重要的特性——Lambda表達式。這篇文章主要介紹了C++ 中l(wèi)ambda表達式的編譯器實現原理,需要的朋友可以參考下
    2017-02-02
  • C語言位運算和sizeof運算符詳解

    C語言位運算和sizeof運算符詳解

    這篇文章主要介紹了C語言位運算和sizeof運算符詳解的相關資料,這里提供了詳細的知識要點,并附簡單代碼示例,需要的朋友可以參考下
    2016-11-11
  • Visual Studio 2019修改編碼UTF-8的實現

    Visual Studio 2019修改編碼UTF-8的實現

    這篇文章主要介紹了Visual Studio 2019修改編碼UTF-8的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-03-03
  • 用C語言實現簡單掃雷游戲

    用C語言實現簡單掃雷游戲

    這篇文章主要為大家詳細介紹了用C語言實現簡單掃雷游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07

最新評論

内丘县| 无为县| 红桥区| 靖宇县| 怀远县| 长子县| 天津市| 金沙县| 和林格尔县| 崇左市| 甘肃省| 内江市| 光山县| 逊克县| 山东| 双柏县| 荣成市| 宜章县| 蓝山县| 公主岭市| 大同市| 简阳市| 乌审旗| 谢通门县| 牟定县| 建湖县| 城口县| 康保县| 定陶县| 吕梁市| 廉江市| 莱阳市| 福贡县| 全南县| 屯昌县| 仪征市| 东莞市| 和林格尔县| 龙川县| 重庆市| 沁水县|