陣列定義和值初始化的語法形式混淆

2021-06-19 16:08:36 字數 1122 閱讀 2338

我們從堆上申請建立乙個包含 12 個整數的陣列,怎麼樣呀?沒問題:  

int *ip = new int(12);  

到目前為止似乎一切正常,那末讓我們在陣列上耍些花樣。耍完以後,再把分配的記憶體予以 **。  

for (int i = 0; i < 12; ++i)  ip[i] = i; delete ip;  

注意我們用的那對空的中括號,它告知編譯器 ip 指涉到的是乙個包含一堆整數的陣列,而 不是單個的乙個整數。等等,事實真的是這樣嗎?  

其實,ip 指涉到的恰恰是單個的乙個整數,被初始化成了 12。我們犯了乙個常見的手誤, 把一對中括號打成了一對小括號。這麼一來,迴圈體裡就會出現非法訪問(索引值大於 0 的部分統統如此),記憶體**這句也行不通了。可是,沒有幾個編譯器能在編譯期就把這個 錯誤給逮出來。因為乙個指標既可以指涉到單個的乙個物件,也可以指涉到包含一堆物件的 陣列,而且迴圈體內的索引語句和陣列的記憶體**語句在語法意義上可謂無懈可擊。這麼一 來,我們直到執行期才會意識到犯了錯誤。

也許連執行期都安然無恙。沒錯,訪問物件陣列所佔空間結束之後的位置是非法的(雖然標 準保證了訪問物件陣列結束之後的乙個物件元素是可以的)(譯註:這是乙個很容易被忽略 的重要補充說明。為什麼要保證訪問陣列後的乙個物件元素是能夠做到的呢?這實際上是為 了和 for 語句的迭代運算元習慣用法相一致,也是 stl 的「前閉後開區間」習慣用法相一致。 但是,如果用指標指涉到了這樣的乙個位置,它是不能被提領的。有關這個問題更詳細的說 明,參見(stroustrup, 2001),§5.3),把應用於陣列的記憶體**語法應用到並非陣列的純量 上也是非法的。但做了非法的事,並不意味著你就沒有機會逍遙法外(想想華爾街**手們 幹的勾當)。以上的**在一些平台能夠完美執行,但在另一些平台上則會在執行時崩潰, 在某些特定平台上還會玩出別的古怪花樣來,到底會如何,就全看特定的執行緒或程序在執行 時是怎麼操作堆記憶體了。正確的記憶體申請語法,當然如下所示:  

int *ip = new int[12];  

說不定,最好的記憶體申請形式就是根本不去自己做這個記憶體申請:直接用標準庫中的元件 就好:  

std::vectoriv(12); for (int i = 0; i < iv.size(); ++i)  iv[i] = i; // 不用顯式地**記憶體(譯註:也不用顯式地申請記憶體)  

陣列的定義和初始化

陣列是相同型別的有序集合。陣列是一種特殊的變數,一次性向計算機申請 一片 連續的空間。通過長度來控制要開闢多少個練習的空間 通過資料型別來控制每個空間的大小。宣告 資料型別陣列名 new 資料型別 長度 陣列的元素 陣列中儲存的具體的值.陣列的長度 陣列中能容納最大的元素的個數。資料下標 陣列是通過...

值初始化和預設初始化

引用 1 值初始化 顧名思義,就是用數值初始化變數。如果沒有給定乙個初始值,就會根據變數或類物件的型別提供乙個初始值。對於int型別其值初始化後的值為0。對於預設初始化內建型別變數來說 1 定義在函式體之外的變數是全域性變數,一般儲存在全域性區,儲存在全域性區的變數一般會執行值初始化。此時,其初始值...

字元陣列的定義和初始化

1 字元陣列的定義與初始化 字元陣列的初始化,最容易理解的方式就是逐個字元賦給陣列中各元素。char str 10 即把10個字元分別賦給str 0 到str 9 10個元素如果花括號中提供的字元個數大於陣列長度,則按語法錯誤處理 若小於陣列長度,則只將這些字元陣列中前面那些元素,其餘的元素自動定為...