實例代碼分析c++動態(tài)分配
1. c語言中動態(tài)分配和釋放
在c中,申請動態(tài)內(nèi)存是使用malloc和free,這兩個函數(shù)是c的標(biāo)準(zhǔn)庫函數(shù),分配內(nèi)存使用的是系統(tǒng)調(diào)用,使用它們必須包含stdlib.h,才能編譯通過。
malloc后需要檢查內(nèi)存是否分配成功,free則要在指針不為空的情況下才能進(jìn)行。
示例代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *p = (char*)malloc(10);
if ( p == NULL)
{
printf("error\n");
}
strncpy(p, "23456", sizeof(p)-1);
printf("p=%s\n", p);
if ( p != NULL)
{
free(p);
p = NULL;
}
return 0;
}
2. c++動態(tài)分配和釋放
c++中,申請動態(tài)內(nèi)存是使用new和delete,這兩個關(guān)鍵字實際上是運算符,并不是函數(shù)。
需要注意的是:new的不是數(shù)組的話,則直接delete就好,并且只會調(diào)用一次析構(gòu)函數(shù),而new[]的話,則需使用delete[]來釋放,并且數(shù)組中每一個元素都會調(diào)用一次析構(gòu)函數(shù),調(diào)用完析構(gòu)函數(shù)再釋放內(nèi)存。
3. new/delete的底層實現(xiàn)
對于基本數(shù)據(jù)類型(無需構(gòu)造函數(shù))而言new是重載了new運算符,調(diào)用了operator new,復(fù)雜數(shù)據(jù)類型則在此基礎(chǔ)上還會調(diào)用構(gòu)造函數(shù),而operator new里面則是調(diào)用的malloc函數(shù),如果調(diào)用malloc失敗,則直接拋出異常;
對于基本數(shù)據(jù)類型(無需析構(gòu)函數(shù))而言delete是重載了delete運算符,調(diào)用了operator delete,復(fù)雜數(shù)據(jù)類型則在此基礎(chǔ)上還會調(diào)用析構(gòu)函數(shù),而operator delete里面則是調(diào)用的free函數(shù)。
4. new[]/delete[]的底層實現(xiàn)
簡單數(shù)據(jù)類型(包括基本數(shù)據(jù)類型和不需要析構(gòu)函數(shù)的類型)
對于簡單數(shù)據(jù)類型而言,new[]調(diào)用的是operator new[],計算出數(shù)組總大小之后調(diào)用operator new。值得一提的是,可以通過()初始化數(shù)組為零值,實例:
char* p = new char[32]();
等同于:
char *p = new char[32]; memset(p,0, 32);
簡單數(shù)據(jù)類型時delete[]則和delete一樣,沒區(qū)別。
復(fù)雜數(shù)據(jù)類型
對于復(fù)雜數(shù)據(jù)類型而言new[]先調(diào)用operator new[]分配內(nèi)存,然后在指針的前四個字節(jié)寫入數(shù)組大小,最后看分配了多少個元素就調(diào)用多少次構(gòu)造函數(shù),之所以要在前4個字節(jié)寫入數(shù)組大小,是因為釋放內(nèi)存之前會調(diào)用每個對象的析構(gòu)函數(shù)。但是編譯器并不知道p實際所指對象的大小。如果沒有儲存數(shù)組大小,編譯器就不知道應(yīng)該調(diào)用幾次析構(gòu)函數(shù);
new[]分配的內(nèi)存只能由delete[]釋放,如果由delete釋放會崩潰,為什么會崩潰呢?
假設(shè)指針p指向new[]分配的內(nèi)存,因為要4字節(jié)存儲數(shù)組大小,實際分配的內(nèi)存地址為[p-4],系統(tǒng)記錄的也是這個地址,delete[]實際釋放的就是p-4指向的內(nèi)存,而delete會直接釋放p指向的內(nèi)存,這個內(nèi)存根本沒有被系統(tǒng)記錄,所以會崩潰。
5. c++中new失敗了怎么辦
根據(jù)前面new實現(xiàn)原理說的,C++里,如果new分配內(nèi)存失敗,默認(rèn)是拋出異常的。所以,如果分配成功,p == NULL就絕對不會成立;而如果分配失敗了,也不會執(zhí)行 if ( p == NULL ),因為分配失敗時,new 就會拋出異常跳過后面的代碼。如果你想檢查 new 是否成功,應(yīng)該捕捉異常:
try {
int* p = new int[SIZE];
// 其它代碼
} catch ( const bad_alloc& e ) {
return -1;
}
當(dāng)然,標(biāo)準(zhǔn) C++ 亦提供了一個方法來抑制 new 拋出異常,而返回空指針,如下:
int* p = new (std::nothrow) int; // 這樣如果 new 失敗了,就不會拋出異常,而是返回空指針 if ( p == NULL ) // 像這樣,這個判斷就有意義了 return -1;
6. delete失敗時是什么現(xiàn)象,一般是因為什么原因
delete失敗可能是因為內(nèi)存在之前已經(jīng)delete過一次了,再次delete就會失敗,linux下報錯:double free or corruption,已放棄。
7. placement new的使用
placement new用于在已經(jīng)分配好的內(nèi)存上,再進(jìn)行二次分配,具體實現(xiàn)如下:
//假設(shè)有類X,成員函數(shù)Do(),代碼如下:
int main()
{
char *buf = new char[sizeof(X)];
X *x = new (buf) X;
x->Do();
x->~X(); //一定要主動調(diào)用析構(gòu)函數(shù)去析構(gòu)
delete []buf;
return 0;
}
以上就是實例代碼分析c++動態(tài)分配的詳細(xì)內(nèi)容,更多關(guān)于c++動態(tài)分配的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺析結(jié)束程序函數(shù)exit, _exit,atexit的區(qū)別
在一個程序中最多可以用atexit()注冊32個處理函數(shù),這些處理函數(shù)的調(diào)用順序與其注冊的順序相反,也即最先注冊的最后調(diào)用,最后注冊的最先調(diào)用2013-09-09
C語言實現(xiàn)超市信息管理系統(tǒng)課程設(shè)計
這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)超市信息管理系統(tǒng)課程設(shè)計,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
C++實現(xiàn)LeetCode(57.插入?yún)^(qū)間)
這篇文章主要介紹了C++實現(xiàn)LeetCode(57.插入?yún)^(qū)間),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++ new與malloc和delete及free動態(tài)內(nèi)存管理及區(qū)別介紹
這篇文章主要介紹了深入理解C++中的new/delete和malloc/free動態(tài)內(nèi)存管理,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12
基于QT和百度云api實現(xiàn)批量獲取PDF局部文字內(nèi)容
這篇文章將為大家介紹如何使用 QT 構(gòu)建圖形用戶界面,結(jié)合百度云 OCR API 實現(xiàn)批量獲取 PDF 局部文字內(nèi)容并對文件進(jìn)行改名的功能,需要的可以參考下2025-03-03
C/C++?Qt?TableDelegate?自定義代理組件使用詳解
TableDelegate自定義代理組件的主要作用是對原有表格進(jìn)行調(diào)整,本文主要介紹了QT中TableDelegate?自定義代理組件的使用教程,感興趣的朋友可以了解一下2021-12-12
C++面試八股文之std::string實現(xiàn)方法
這篇文章主要介紹了C++面試八股文:std::string是如何實現(xiàn)的,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06

