C++ 動態(tài)內(nèi)存分配詳解(new/new[]和delete/delete[])
一、為什么需要動態(tài)內(nèi)存分配?
在C++程序中,所有內(nèi)存需求都是在程序執(zhí)行之前通過定義所需的變量來確定的。 但是可能存在程序的內(nèi)存需求只能在運行時確定的情況。 例如,當(dāng)需要的內(nèi)存取決于用戶輸入。 在這些情況下,程序需要動態(tài)分配內(nèi)存,C ++語言將運算符new和delete合成在一起。
(1)特點
- 1.C++中通過new關(guān)鍵字進行動態(tài)內(nèi)存申請
- 2.C++中的動態(tài)內(nèi)存分配是基于類型進行的
- 3.delete關(guān)鍵字用于內(nèi)存釋放
(2)語法
①變量申請:
Type* pointer = new Type; //... delete pointer;
表達(dá)式用于分配內(nèi)存以包含一個類型類型的單個元素。
②數(shù)組申請:
Type* pointer = new Type[N]; //... delete[] pointer;
表示用于分配類型類型的元素的塊(數(shù)組),其中N是表示這些元素的量的整數(shù)值。
Example:
int * foo; foo = new int [5];
在這種情況下,系統(tǒng)為int類型的五個元素動態(tài)分配空間,并返回指向序列的第一個元素的指針,該指針被分配給foo(指針)。 因此,foo現(xiàn)在指向一個有效的內(nèi)存塊,其中包含五個int類型元素的空間。
這里,foo是一個指針,因此,foo指向的第一個元素可以使用表達(dá)式foo [0]或表達(dá)式* foo(兩者都是等價的)來訪問??梢允褂胒oo [1]或*(foo + 1)訪問第二個元素,依此類推......
Note:
我們程序請求的動態(tài)內(nèi)存由系統(tǒng)從內(nèi)存堆中分配。 但是,計算機內(nèi)存是一種有限的資源,它可能會耗盡。 因此,無法保證所有使用operator new分配內(nèi)存的請求都將由系統(tǒng)授予。
(3)動態(tài)內(nèi)存分配Example:
#include <stdio.h> int main() { int* p = new int; *p = 5; *p = *p + 10; printf("p = %p\n", p); printf("*p = %d\n", *p); delete p; p = new int[10]; for(int i=0; i<10; i++) { p[i] = i + 1; printf("p[%d] = %d\n", i, p[i]); } delete[] p; return 0; }
編譯運行,結(jié)果:
p = 007F77D8
*p = 15
p[0] = 1
p[1] = 2
p[2] = 3
p[3] = 4
p[4] = 5
p[5] = 6
p[6] = 7
p[7] = 8
p[8] = 9
p[9] = 10
請按任意鍵繼續(xù). . .
二、new關(guān)鍵字與malloc函數(shù)的區(qū)別
new關(guān)鍵字是C++的一部分 | malloc是由C庫提供的函數(shù) |
new以具體類型為單位進行內(nèi)存分配 | malloc以字節(jié)為單位進行內(nèi)存分配 |
new在申請單個類型變量時可進行初始化 | malloc不具備內(nèi)存初始化的特性 |
三、new關(guān)鍵字的初始化:
int* pi = new int(1); float* pf = new float(2.0f); char* pc = new char('c');
Test:
#include <stdio.h> int main() { int* pi = new int(1); // int* pa = new int[1]; float* pf = new float(2.0f); char* pc = new char('c'); printf("*pi = %d\n", *pi); printf("*pf = %f\n", *pf); printf("*pc = %c\n", *pc); delete pi; delete pf; delete pc; return 0; }
輸出結(jié)果:
*pi = 1
*pf = 2.000000
*pc = c
請按任意鍵繼續(xù). . .
注意:
int* pi = new int(1);表示動態(tài)分配一個int ,初始化為 1int* pa = new int[1];表示動態(tài)分配一個數(shù)組,數(shù)組大小為1
四、C++動態(tài)分配內(nèi)存異常機制
事項一下,我們的計算機內(nèi)存優(yōu)先,如果我們分配一個很大的內(nèi)存空間,會出現(xiàn)棧滿,程序產(chǎn)生異常,程序崩潰。所以我們需要引入異常機制。
C ++提供了兩種標(biāo)準(zhǔn)機制來檢查分配是否成功。
(1)一個是處理異常。
使用此方法,在分配失敗時拋出bad_alloc類型的異常。 例外是這些教程后面解釋的強大的C ++特性。 但是現(xiàn)在,您應(yīng)該知道如果拋出此異常并且未由特定處理程序處理,則程序執(zhí)行將終止。
此異常方法是new默認(rèn)使用的方法,并且是在聲明中使用的方法,like:
foo = new int [5]; // if allocation fails, an exception is thrown
(2)另一種方法稱為nothrow
當(dāng)使用它時會發(fā)生的情況是,當(dāng)內(nèi)存分配失敗時,而不是拋出bad_alloc異?;蚪K止程序,new返回的指針是空指針,程序繼續(xù)正常執(zhí)行 。
可以使用名為nothrow的特殊對象(在header <new>中聲明)作為new的參數(shù)來指定此方法:
foo = new (nothrow) int [5];
在這種情況下,如果此內(nèi)存塊的分配失敗,則可以通過檢查foo是否為空指針來檢測異常:
int * foo; foo = new (nothrow) int [5]; if (foo == nullptr) { // error assigning memory. Take measures. }
異常處理Example:
// rememb-o-matic #include <iostream> #include <new> using namespace std; int main () { int i,n; int * p; cout << "How many numbers would you like to type? "; cin >> i; p= new (nothrow) int[i]; if (p == nullptr) cout << "Error: memory could not be allocated"; else { for (n=0; n<i; n++) { cout << "Enter number: "; cin >> p[n]; } cout << "You have entered: "; for (n=0; n<i; n++) cout << p[n] << ", "; delete[] p; } return 0; }
編譯運行,結(jié)果:
參考資料:
1)唐佐林 《C++深度解析教程》
到此這篇關(guān)于C++ 動態(tài)內(nèi)存分配詳解(new/new[]和delete/delete[])的文章就介紹到這了,更多相關(guān)C++ 動態(tài)內(nèi)存分配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++數(shù)據(jù)序列化方式(自定義結(jié)構(gòu)體的保存和讀取)
這篇文章主要介紹了C++數(shù)據(jù)序列化方式(自定義結(jié)構(gòu)體的保存和讀取),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08C語言學(xué)生成績管理系統(tǒng)小設(shè)計
這篇文章主要為大家詳細(xì)介紹了C語言學(xué)生成績管理系統(tǒng)小設(shè)計,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01深入C++中構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、賦值操作符、析構(gòu)函數(shù)的調(diào)用過程總結(jié)
本篇文章是對C++中構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、賦值操作符、析構(gòu)函數(shù)的調(diào)用過程進行了總結(jié)與分析,需要的朋友參考下2013-05-05