————————————————————————————————————
我們知道,使用malloc/calloc等分配內存的函數時,一定要檢查其返回值是否爲“空指針”(亦即是檢查分配內存的操作是否成功),這是良好的編程習慣,也是編寫可靠程序所必需的。但是,如果你簡單的把這一招應用到new上,那就不一定正確了。
C++裏,如果new分配內存失敗,默認是拋出異常的。如果你想檢查new是否成功,應該捕捉異常。
try{ int* p = new int[SIZE]; //其他代碼 }catch( const bad_alloc& e ){ return -1; }
當然,標準的C++亦提供了一個方法來抑制new拋出異常,而返回空指針:
int* p = new (std::nothrow) int; //這樣,如果new失敗了,就不會拋出異常,而是返回空指針 if( p==0 )//如此這般,這個判斷就有意義了 return -1; //其他代碼
——————————————————————以上都是無用之談
new的語法格式:new 數據類型(初始化參數列表);
關於new後加()與不加()的區別:
在用new建立一個類的對象時,若存在用戶定義的默認構造函數,則new T和new T()兩寫法效果相同,都會調用此默認構造函數;若未定義,new T會調用系統默認構造函數,new T()除了調用系統默認構造函數,還會給基本數據類型和指針類型的成員用0賦值,且該過程是遞歸的。即若該對象的某個成員對象未定義默認構造函數,那麼該成員對象的基本數據類型和指針類型的成員同樣會被以0賦值。
故用new的時候請加上()。
運算符delete用來刪除由new建立的對象,釋放指針所指向的內存空間。
——————————————————————
關於new數組類型的對象:
語法格式: new 類型名 [數組長度];
delete[] 指針名;
如int* p = new int[10]();
delete[] p;
——————————————————————
多維數組:
語法格式: new 類型名T[第一維長度][第二維長度]...;
其中第1維長度是任何結果爲正整數的表達式,其餘必須是正整數的常量表達式(因爲是常量,故不能直接分配兩維都不固定的數組)。
若內存申請成功,返回指向新分配內存的首地址的指針,但不是T類型指針,而是指向T類型數組的指針,數組元素的個數爲除第一維外各維下標表達式的乘積。
如int (*p)[25][10]; //請把p抽出來看,p的類型爲 int* [25][10]
p = new int[10][25][10];
則指針p即可以作爲指針用,也可以當一個三維數組名用。
再舉例如下:
int *p = new int[10]; //返回一個指向int的指針int*. int (*p)[10] = new int[2][10]; //new了一個二維數組,返回一個指向int[10]這種一維數組的指針int(*)[10]. int (*p)[2][10] = new int[5][2][10]; //new了一個三維數組,返回一個指向二維數組int[2][10]這種類型的指針int (*)[2][10].
注意:new int[0][10]和new int[][10]都是無分配內存。
那麼如果第二維都不確定怎麼辦呢?
int **a = new int*[n]; for(int i = 0; i < n; i++) a[i] = new int[n](); //分配n*n的數組,還可以a[i] = new int[i]();有點java的味道... for(int i = 0; i < n; i++) delete[] a[i]; delete[] a;
當char * a=new char[10]後,程序結束需要delete [] a請問爲什麼不需要寫delete [10] a ,即計算機是怎麼知道是數組大小的?
參考以下鏈接: https://blog.csdn.net/hazir/article/details/21413833
How do compilers use “over-allocation” to remember the number of elements in an allocated array?
// Original code: Fred* p = new Fred[n]; char* tmp = (char*) operator new[] (WORDSIZE + n * sizeof(Fred)); Fred* p = (Fred*) (tmp + WORDSIZE); *(size_t*)tmp = n; size_t i; try { for (i = 0; i < n; ++i) new(p + i) Fred(); // Placement new } catch (...) { while (i-- != 0) (p + i)->~Fred(); // Explicit call to the destructor operator delete[] ((char*)p - WORDSIZE); throw; }
// Original code: delete[] p; size_t n = * (size_t*) ((char*)p - WORDSIZE); while (n-- != 0) (p + n)->~Fred(); operator delete[] ((char*)p - WORDSIZE);
How do compilers use an “associative array” to remember the number of elements in an allocated array?
// Original code: Fred* p = new Fred[n]; Fred* p = (Fred*) operator new[] (n * sizeof(Fred)); size_t i; try { for (i = 0; i < n; ++i) new(p + i) Fred(); // Placement new } catch (...) { while (i-- != 0) (p + i)->~Fred(); // Explicit call to the destructor operator delete[] (p); throw; } arrayLengthAssociation.insert(p, n);
// Original code: delete[] p; size_t n = arrayLengthAssociation.lookup(p); while (n-- != 0) (p + n)->~Fred(); operator delete[] (p);
參考鏈接:https://isocpp.org/wiki/faq/compiler-dependencies#num-elems-in-new-array-overalloc
malloc/free與new/delete的策略類似,new/delete是malloc/free的上層
https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array
====================================================================
隱式空閒鏈表(任何操作的開銷都與堆中已分配塊和未分配塊的總數呈線性關係)
帶邊界標記的合併(塊分配與堆塊的總數呈線性關係,合併空閒塊常數時間)
顯式空閒鏈表(分配時間從塊總數減少爲空閒塊數量的線性時間,釋放時間取決於空閒鏈表塊的排序策略,LIFO則常數時間釋放,按地址順序排序則線性時間釋放,如果採用了邊界標記,合併時間常數)
分離的空閒鏈表:簡單分離存儲 / 分離適配 / 夥伴系統