vc
動態陣列實現
陣列型別的變數有三個重要的限制:陣列長度固定不變,在編譯時必須知道其長度,陣列只在定義它的塊語句內存在.
實際的程式往往不能忍受這樣的限制-------它們需要在執行時 動態地分配陣列.雖然陣列長度是固定的,但動態分配的陣列不必在編譯時知道其長度,可以(通常也是)在執行時才確定陣列長度.與陣列變數不同,動態分配的陣列將一直存在,知道程式顯式釋放它為止.
每乙個程式在執行時都占用一款可用的記憶體空間,用於存放動態分配的物件,此記憶體空間稱為程式的自由儲存區(free store)或堆(heap).c語言程式使用一對標準庫函式malloc和free在自由儲存區中分配儲存空間,而c++語言則使用new和delete表示式實現相同的功能。 1.
動態陣列的定義
陣列變數通過指定型別、陣列名和維數來定義
.而動態分配陣列時,只需指定型別和陣列長度,不必為陣列物件命名,new表示式返回指向新分配陣列的第乙個元素的指標:
int *pia=newint[10]; //array of 10 uninitialized ints
此new表示式分配了乙個含有10個int型元素的陣列,並返回指向該陣列第乙個元素的指標,此返回值初始化了之怎pia.
new表示式需要指定指標型別以及在方括號中給出的陣列維數,該維數可以是任意的複雜表示式.建立陣列後,new將返回指向陣列第乙個元素的指標.在自由儲存區中建立的陣列物件是沒有名字的,程式設計師只能通過其位址間接地訪問堆中的物件. 2.
初始化動態分配的陣列
動態分配陣列時,如果陣列元素具有類型別,將使用該類的預設建構函式實現初始化;如果陣列元素是內建型別,則無初始化:
string *psa=new string[10]; //array of 10 empty strings
int *pia=new int[10]; //array of 10 ninitialized ints
這兩個new表示式都分配了含有10個物件的陣列.其中第乙個陣列是string型別,分配了儲存物件的記憶體空間後,將呼叫string型別的預設建構函式依次初始化陣列中的每個元素(實際上string物件都是空串,結尾無『\0』).第二個陣列則具有內建型別的元素,分配了儲存10個int物件的記憶體空間,但這些元素沒有初始化.
也可使用跟在陣列長度後面的一對空圓括號,對陣列元素做值初始化:
int *pia2=new int[10](); //array of 10 uninitialized ints
圓括號要求編譯器對陣列做值初始化,在本例中即把陣列元素都設定為0. 註解
:對於動態分配的陣列,其元素只能初始化為元素型別的預設值,而不能像陣列變數一樣,用初始化列表為陣列元素提供各不相同的初值.
3.const
物件的動態陣列
如果我們在自由儲存區中建立的陣列儲存了內建型別的const物件,則必須為這個陣列提供初始化:因為陣列元素都是const物件,無法賦值.實現這個要求的唯一方法是對陣列做值的初始化:
//error:uninitialized const array
const int *pci_bad=new const int[100];
//ok:value-initialized const array
const int *pci_ok=new const int[100]();
c++允許定義類型別的const陣列,但該類型別必須提供預設建構函式:
//ok:array of 100 empty strings
const string *pcs=new const string[100];
在這裡,將使用string類的預設建構函式初始化陣列元素.
當然,已建立的常量元素不允許修改------因此這樣的陣列實際上用處不大. 4.
允許動態分配空陣列
之所以要動態分配陣列,往往是由於編譯時並不知道陣列的長度.我們可以編寫如下**
size_t n=get_size(); //get_size returns number of elements needed
int *p=new int[n];
for(int *q=p;q!=p+n;++q)
/* process the array */;
計算陣列長度,然後建立和處理該陣列.
有趣的是,如果get_size返回0會怎麼樣?答案是:**仍然正確執行.c++雖然不允許定義長度為0的陣列變數,但明確指出,呼叫new動態建立長度為0的陣列是合法的:
char arr[0]; //error:cannot define zero-length array
char *cp=new char[0]; //ok:but cp can't be dereferenced
用new動態建立長度為0的陣列時,new返回有效的非零指標.該指標與new返回的其他指標不同,不能進行解引用操作,因為它畢竟沒有指向任何元素.而允許的操作包括:比較運算,因此該指標能在迴圈中使用;在該指標上加(減)0,或者減去本身值,得0值.
在上述例題中,如果get_size返回0,則仍然可以成功呼叫new,但是p並沒有指向任何物件,陣列是空的.因為n為0,所以for迴圈實際比較的是p和q,而q是用p初始化的,兩者具有相等的值,因此for迴圈條件不成立,迴圈體一次都沒有執行 5.
動態空間的釋放
動態分配的記憶體最後必須進行釋放,否則,記憶體最終將會逐漸耗盡.如果不再需要使用動態建立的陣列,程式設計師必須顯式地將其占用的儲存空間返還給程式的自由儲存區.c++語言為指標提供delete表示式釋放指標所指向的陣列空間:
delete pia;
該語句**了pia所指向的陣列,把相應的記憶體返還給自由儲存區.在關鍵字delete和指標之間的空方括號對是必不可少的:它告訴編譯器該指標指向的是自由儲存區中的陣列,而並非單個物件. 小心
:如果遺漏了空方括號對,這是乙個編譯器無法發現的錯誤,將導致程式在執行時出錯.
理論上,**陣列時缺少空方括號對,至少會導致執行時少釋放了記憶體空間,從而產生記憶體洩漏(memory leak).對於某些系統和/或元素型別,有可能會帶來更嚴重的執行時錯誤.因此,在釋放動態陣列時千萬別忘了方括號對. c
風格字串與c++的標準庫型別string的比較:
以下兩段程式反映了使用c風格字串與c++的標準庫型別string的不同之處.使用string型別的版本更短、更容易理解,而且出錯的可能性更小:
//c-style character string implementation
const char *pc="a very long literal string";
const size_t len=strlen(pc +1); //space to allocate
//performance test on string allocation and copy
for(size_t ix=0;ix!=1000000;++ix)
//string implementation
string str("a very long literal string");
//performance test on string allocation and copy
for(int ix=0;ix!=1000000;++ix) //str2 is automatically freed 6.
動態陣列的使用
通常是因為在編譯時無法知道陣列的維數,所以才需要動態建立該陣列.例如,在程式執行過程中,常常使用char*指標指向多個c風格字串,於是必須根據每個字串的長度實時地動態分配儲存空間.採用這種技術要比建立固定大小的陣列安全.如果程式設計師能夠準確計算出執行時需要的陣列長度,就不必再擔心因陣列變數具有固定的長度而造成的溢位問題.
假設有以下c風格字串:
const char *noerr="success";
//...
const char *err189="error: a function declaration must "
"specify a function return type!";
我們想在執行時把這兩個字串中的乙個複製給新的字元陣列,於是可以用以下程式在執行時計算維數:
const char *errortxt;
if(errorfound)
errortxt=err189;
else
errortxt=noerr;
//remember the 1 for the terminating null
int dimension=strlen(errortxt)+1;
char *errmsg=new char[dimension];
//copy the text for the error into errmsg
strncpy (errmsg,errortxt,dimension);
別忘記標準庫函式strlen返回的是字串的長度,並不包括字串結束符,在獲得的字串長度上必須加1以便在動態分配時預留結束符的儲存空間.
vc 簡單的vector動態陣列實現
1 ifndef myvector 2 define myvector 3 include 4 define success 1 成功 5 define errors 1 失敗 6 define malloc error 2 申請記憶體失敗 7 define index error 3 錯誤的索引號...
實現動態陣列
學過c語言的都知道陣列的長度在定義陣列時時固定的,不能在程式執行時發生變化,那麼動態陣列是否和以上的定義相違背?動態陣列的實現步驟 1.先使用malloc函式申請乙個足夠大的位址空間,並返回乙個指標作為首位址 2.將原有陣列的元素按照順序複製到新的位址中 3.將帶加入的元素加入到新的位址中並且時放在...
動態陣列的實現
靜態陣列 編譯階段確定陣列的大小,執行階段不能改變陣列大小。缺點是事先無法準確確定陣列的大小,太小不滿足處理需要,太大浪費記憶體空間。動態陣列 執行階段,根據實際需要動態確定陣列的大小。在 c 語言中,可利用記憶體的申請和釋放庫函式,c語言培訓班 以及指向陣列的指標變數可當陣列名使用的特點,來實現動...