c++語言和標準庫提供了兩種一次分配乙個物件陣列的方法。c++語言定義了另一種new表示式語法,可以分配並初始化乙個物件陣列。標準庫中包含乙個名為allocator的類,允許我們將分配和初始化分離。使用allocator通常會提供更好的效能和更靈活的記憶體管理能力。
為了讓new分配乙個物件陣列,我們要在型別名之後跟一對方括號,在其中指明要分配的物件的數目。在下例中,new分配要求數量的物件並(假定分配成功後)返回指向第乙個物件的指標:
int get_size_new()
void new_array()
delete p_array;
cout << endl;
}
在main函式中呼叫new_array會輸出42個0,因為new 分配的陣列初始值都為0。
為了釋放動態陣列,我們使用一種特殊形式的delete——在指標前加上乙個空方括號對.
方括號中的大小必須是整型,但不必是常量。也可以用乙個表示陣列型別的型別別名,來分配乙個陣列,這樣,new表示式中就不需要方括號了:
void new_array()
雖然我們通常稱new t
分配的記憶體為「動態陣列」,但這種叫法某種程度上有些誤導。
當用new分配乙個陣列時,我們並未得到乙個陣列型別的物件,而是得到乙個陣列元素型別的指標。
即使我們使用型別別名定義了乙個陣列型別,new也不會分配乙個陣列型別的物件。new返回的是乙個元素型別的指標。
由於分配的記憶體並不是乙個陣列型別,因此不能對動態陣列呼叫begin或end。
要記住我們所說的動態陣列並不是陣列型別,這是很重要的。
可以通過{}初始化動態陣列
void new_array()
初始化動態陣列
int *p_array = new int[10];
//釋放動態陣列
delete p_array;
}
如果{}初始化列表小於陣列長度,則預設補充空值,int補充0,string補充空字串。
動態分配乙個大小為0的陣列是合法的
void new_array()
delete p_array;
}
當n為0時,開闢了乙個長度為0的動態陣列,因為迴圈條件p != n+p_array,所以不會進入迴圈。
當我們用new分配乙個大小為0的陣列時,new返回乙個合法的非空指標。此指標保證與new返回的其他任何指標都不相同。
對於零長度的陣列來說,此指標就像尾後指標一樣,我們可以像使用尾後迭代器一樣使用這個指標。
可以用此指標進行比較操作,就像上面迴圈**中那樣。可以向此指標加上(或從此指標減去)0,也可以從此指標減去自身從而得到0。但此指標不能解引用——畢竟它不指向任何元素。
標準庫提供了乙個可以管理new分配的陣列的unique_ptr版本。為了用乙個unique_ptr管理動態陣列,我們必須在物件型別後面跟一對空方括號:
void unique_array()
型別說明符中的方括號
指出up指向乙個int陣列而不是乙個int。由於unarray指向乙個陣列,當unarray銷毀它管理的指標時,會自動使用delete。
當乙個unique_ptr指向乙個陣列時,我們可以使用下標運算子來訪問陣列中的元素:
void unique_array()
//釋放這個動態陣列
unarray.release();
}
shared_ptr也可以管理動態陣列,這一點在c++ primer 第5版裡沒有提及,但是我自己測試好用
void shared_array()
); for (int i = 0; i < 5; i++)
sharray.reset();
cout << endl;
}
c++ primer 第5版推薦的用法如下
void use_shared_array()
); sharray.reset();
}
上例中,shared_ptr管理乙個動態陣列並提供了刪除器。
當分配一大塊記憶體時,我們通常計畫在這塊記憶體上按需構造物件。在此情況下,我們希望將記憶體分配和物件構造分離。這意味著我們可以分配大塊記憶體,但只在真正需要時才真正執行物件建立操作(同時付出一定開銷)。
類似vector,allocator是乙個模板。為了定義乙個allocator物件,我們必須指明這個allocator可以分配的物件型別。
當乙個allocator物件分配記憶體時,它會根據給定的物件型別來確定恰當的記憶體大小和對齊位置:
void use_allocator()
上述**用allocator構造alloc物件,說明開闢的空間是為string物件準備的,然後呼叫allocate開闢空間,但是這些空間不能直接使用,需要呼叫建構函式才能使用,我們用allocator類的construct來構造物件。
void use_allocator()
// //列印構造的字串列表
for (q = p; q != p + 5; q++)
//銷毀開闢的空間
alloc.deallocate(p, 5);
}
迴圈中通過construct為每個q指向的空間構造string物件,物件的內容就是str的內容,str會隨著迴圈每次增加c,所以上面的**輸出如下
c
ccccc
cccc
ccccc
另外stl也提供了一些拷貝和填充記憶體的演算法
void use_allocator()
; allocatoralloc;
//開闢2倍ivec大小的空間
auto p = alloc.allocate(ivec.size() * 2);
//將ivec的內容copy至alloc開闢的空間裡
//返回q指向剩餘未構造的記憶體空間的起始位址
auto q = uninitialized_copy(ivec.begin(), ivec.end(), p);
//將剩餘元素初始化為42
uninitialized_fill_n(q, ivec.size(), 42);
}
通過uninitialized_copy將ivec元素拷貝到p指向的空間,同樣完成了構造。
uninitialized_fill_n將剩餘ivec大小未構造的空間全部初始化為42。
本文介紹了動態陣列開闢的方法,利用new關鍵字可以開闢動態陣列,利用delete可以**陣列。
也實現了通過shared_ptr和unique_ptr等智慧型指標管理動態陣列的方案。
最後通過列舉allocator的一些方法,展示了如何實現開闢空間和構造物件分離的方式動態構造物件。
原始碼連線
想系統學習更多c++知識,可點選下方鏈結。
c++基礎
C 動態陣列
原 1.變長一維陣列 這裡說的變長陣列是指在編譯時不能確定陣列長度,程式在執行時需要動態分配記憶體空間的陣列。實現變長陣列最簡單的是變長一維陣列,你可以這樣做 1 檔名 array01.cpp 2 include 3 using namespace std 4 int main 5 注意int p ...
c 動態陣列
在建立動態陣列的過程中我們要遵循乙個原則,那就是在建立的時候從外層往裡層,逐層建立 而釋放的時候從裡層往外層,逐層釋放。這個話你讀了可能理解並不深刻,不過不要急,接下來我們看看兩段 一維動態陣列的建立 include include int main int n1,i int array print...
c 動態陣列
這學期學c 晚上有道程式設計題,比較坑,感覺要用動態陣列做,但實際就是要用靜態陣列,因為動態的反而更難了。用動態陣列的時候,發現自己只會建立一維的 int a new int 5 然後二維陣列怎麼創都忘記了,還是那句話 不寫 很容易 忘記。然後下面就給出幾個例子吧 cpp view plain co...