與vector的異同
- 相同:都是存放類型相同對象的容器
- 不同:數組的大小確定不變,不能隨意向數組中增加元素
1、定義和初始化內置數組
數組中元素的個數也屬於數組類型的一部分,編譯的時候維度應該是已知的,也就是說,維度必須是一個常量表達式。
默認情況下,數組的元素被默認初始化。
NOTE:
- 定義數組的時候必須制定數組類型,不允許用auto
- 數組元素應爲對象,不能是引用
顯式初始化數組元素
可以對數組元素進行列表初始化,此時允許忽略數組的維度。當指定了維度,則維度應比列表初始值的數量多,當維度比初始化列表的數量大時,多的部分默認初始化。
字符數組的特殊性
字符數組允許用字符串字面值來進行初始化,但數組的維度必須比字符串字面值大1,用來盛放添加的空字符'/0';
char a[]="hi"; char a1[2]="hi"; //錯誤,最後的空字符'/0'沒地方放
不允許拷貝和賦值
不能將數組的內容拷貝給其他數組作爲初始值,也不能用數組爲其他數組賦值
int a[]={0,1,2}; int b[]=a; //不允許使用一個數組初始化另一個數組 int b=a; //不允許把數組直接賦值給另一數組
理解複雜的數組聲明
數組本身也是對象,因此可以定義指向數組的指針和引用。
1 2 3 4 |
|
2、訪問數組元素
可以使用範圍for語句或下標來訪問數組元素
在使用下標的時候,通常將其定義爲size_t類型。size_t類型是一種機器相關的無符號類型,它被設計得足夠大以便能表示內存中任意對象的大小。在cstddef頭文件中定義了size_t類型。
遍歷數組所有元素,最好的方法是範圍for語句。
檢查下標的值
3、指針和數組
在很多用到數組名字的地方,編譯器都會自動地將其替換爲一個指向數組首元素的指針。
對數組的元素使用取地址符就能得到指向該元素的指針。
指針也是迭代器
指向數組元素的指針可以執行迭代器一樣的操作。
int a[10] = { 0 }; int n = 0; for (auto &i : a) { i = n; n++; } int *p1 = a; //相當於迭代器的begin int *p2 = &a[10]; //相當於迭代器的end for (int *p3 = p1; p3 != p2; p3++) { cout << *p3 << endl; }
標準庫函數begin和end
上述使用a[10]的地址來表示尾後指針很容易出錯,因此標準庫定義了數組用的begin和end函數來得到數組的首指針和尾後指針,其在iterator頭文件中。
int a[10] = { 0 }; int n = 0; for (auto &i : a) { i = n; n++; } /*int *p1 = a; int *p2 = &a[10];*/ int *p1 = begin(a); int *p2 = end(a); for (int *p3 = p1; p3 != p2; p3++) { cout << *p3 << endl; }
二者同樣的效果。
指針運算
給指針加上一個整數,得到的新指針仍需指向同一數組的其他元素,或者指向同一數組的尾元素的下一位置。
解引用和指針運算的交互
指針加上一個整數得到的結果仍是一個指針,因此可以解引用該指針。
下標和指針
對數組執行下標運算其實是對指向數組元素的指針執行下標運算。
int i=a[2]; //上面的下標引用其實是下面的過程 int *p=a; i=*(p+2);
雖然標準庫類型vector和string也能執行下標運算,但是數組與它們相比還是有所不同。標準庫類型限定使用的下標必須是無符號類型,而內置的下標運算無此要求。
int *p=&a[2]; int j=p[1]; //實際是a[3] int k=p[-2]; //實際上是a[0]
與舊代碼的接口
混用string對象和C風格字符串
C風格字符串:以空字符結尾的字符數組。
string提供一個名爲c_str()的成員函數來將string轉換爲C風格字符串,返回的是const char*類型。
使用數組初始化vector對象
指明要拷貝區域的首元素地址和尾後地址即可。
int a[]={0,1,2,3,4,5}; vector<int> v(begin(a),end(a));
NOTE:不能用vector初始化數組。
- 儘量不使用數組和指針,而使用vector和迭代器
- 儘量不使用C風格字符串,而使用string
多維數組
C++語言中沒有多維數組,通常所說的多維數組其實是數組的數組。
int a[3][4]; //大小爲3的數組,每個元素是含有4個整數的數組 int b[10][20][30];
多維數組的初始化
使用花括號括起來的一組值初始化多維數組,和普通數組初始化一樣,只是數組的元素也是數組而已。
int a[3][4]={ {0,1,2,3}, {4,5,6,7}, {8,9,10,11}}; int a[3][4]={0,,1,2,3,4,5,6,7,8,9,10,11}; //和上面的效果一樣 int a[3][4]={{0},{1},{3}}; //其餘的默認初始化
多維數組的下標引用
表達式含有的下標運算符數量和數組的維度一樣多,該表達式的結果將是給定類型的元素;當比數組的 維度數量小時,表示的是內層數組。
使用範圍for語句處理多維數組
size_t cnt=0; for(auto &row:a) for(auto &col:row) col=cnt; cnt++; }
NOTE:
使用範圍for語句處理多維數組,除了最內層的循環外,其他所有循環的控制變量都應用是引用類型。爲了防止編譯器將auto控制變量轉換成數組首元素的指針。
指針和多維數組
當程序使用多維數組的名字時,也會自動將其轉換成指向數組首元素的指針。
也可以通過使用auto或decltype來遍歷多維數組
int a[3][4] = {}; int cnt = 0; for (auto p = a; p != a + 3; p++) { for (auto q = *p; q != *p + 4; q++) { *q = cnt; cnt++; } } for (auto p = a; p != a + 3; p++) { for (auto q = *p; q != *p + 4; q++) { cout << *q << " | "; } cout << endl; }
也可以使用begin和end來簡化
int a[3][4] = {}; int cnt = 0; for (auto p = begin(a); p != end(a); p++) { for (auto q = begin(*p); q != end(*p); q++) { *q = cnt; cnt++; } } for (auto p = begin(a); p != end(a); p++) { for (auto q = begin(*p); q != end(*p); q++) { cout << *q << " | "; } cout << endl; }
類型別名簡化多維數組的指針
using int_array=int[4]; int a[3][4] = {}; int cnt = 0; for (auto p = begin(a); p != end(a); p++) { for (auto q = begin(*p); q != end(*p); q++) { *q = cnt; cnt++; } } for (int_array *p = a; p != a + 3; p++) { for (int *q = *p; q != *p + 4; ++q) { cout << *q << " | "; } cout << endl; }