C 動態陣列

2022-09-19 09:18:10 字數 3561 閱讀 9782

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...