數組
數組(array)是一種數據格式,能夠存儲多個同類型的值。每個值都存儲在一個獨立的數組元素中,計算機在內存中依次存儲數組的各個元素。要創建數組,可使用聲明語句。數組聲明應指出以下三點:
- 存儲在每個元素中的值的類型;
- 數組名
- 數組中的元素數
在C++中,可以通過修改簡單變量的聲明,添加中括號(其中包含元素數目)來完成數組聲明。例如,下面的聲明創建一個名爲 months的數組,該數組有12個元素,每個元素都可以存儲一個 short類型:
short months[12]
聲名數組的通用格式如下
typeName arrayName[arraySize];
表達式 arraySize指定元素數目,它必須是整型常數(如10)或const值,也可以是常量表達式(如8·
sizeof(int),即其中所有的值在編譯時都是已知的。具體地說, arraySize不能是變量,變量的值是在程序時設置的。
數組的很多用途都是基於這樣一個事實:可以單獨訪問數組元素,方法是使用下標或索引來對元素進行編號。C++數組從0開始編號。C++使用帶索引的方括號表示法來指定數組元素,例如, months[0]是 months數組的第一個元素, months[11]是最後一個元素。注意,最後一個元素的索引比數組長度小1(參見圖1)。因此,數組聲明能夠使用個聲明創建大量的變量,然後便可以用索引來標識和訪問各個元素
數組的初始化規則
只有定義數組時才能使用初始化,此後就不能使用了,也不能將一個數組賦給另一個數組:
int cards[4] = {3,6,8,10}; //okay
int hand[4]; //okay
hand[4] = {5,6,7,9}; //not okay
hand = cards; // not okay
也可以使用下標分別給數組中的元素賦值。
初始化數組時,提供的值可以少於數組的元素數目。例如,下面的語句只初始化hotelTips的前兩個元素:
float hotelTips[5] = {5.0,2.5};
如果只對數組的一部分進行初始化,則編譯器將把其他元素設置爲0.因此,將數組中所有的元素都初始化爲0非常簡單—只要顯式地將第一個元素初始化爲0,然後讓編譯器將其他元素都初始化爲0;
long totals[500] = {0};
如果初始化爲{1} 而不是{0},則第一個元素設置爲1,其他元素被設置爲0。
如果初始化數組時方括號內([])爲空,C++編譯器將計算元素個數,例如,對於下面的聲名:
short things[] = {1, 5, 3, 8}
編譯器將使things數組包含4個元素。
C++11初始化方法
C++使用大括號的初始化(列表初始化)作爲一種通用初始化方法,可用於所有類型。數組以前就可使用列表初始化,但C++中列表初始化新增了一些功能。
1.初始化數組時,可以省略等號(=)
double earnings[4] {1.2e4,1.6e4,1.1e4,1.7e4};
2.可在大括號內不包含任何東西,這將把所有元素都設置爲零:
unsigned int counts[10]={}; //all elements set to 0
float balances[100] {} //all elements set to 0
3.列表初始化禁止縮窄轉換
long plifs[] = {25,92,3.0} // not allowed
char slifs[4] {'h','i',1122011,'\0'} // not allowed
char tlifs[4] {'h','i',112,'\0'} //allowed
在上述代碼中,第一條語句不能通過編譯,因爲將浮點數轉換爲整型是縮窄操作,即使浮點數的小數點後面爲零。第二條語句也不能通過編譯,因爲1122011超出了char變量的取值範圍(這裏假設char變量的長度爲8位)。第三條語句可通過編譯,因爲雖然112是一個int值,但它在char變量的取值範圍內。
數組的替代品
模板類vector和array是數組的替代品;這些替代品對於數組的創建和使用更加靈活簡便。
模板類vector
模板類 vector類似於 string類,也是一種動態數組。可以在運行階段設置 vector對象的長度,可在末尾附加新數據,還可在中間插入新數據。基本上,它是使用new創建動態數組的替代品。實際上, vector類確實使用new和 delete來管理內存,但這種工作是自動完成的.
這裏不深入探討模板類意味着什麼,而只介紹一些基本的實用知識。首先,要使用 vector對象,必須包含頭文件 vector。其次, vector包含在名稱空間std中,因此可使用 using編譯指令、 using聲明或std:vector e第三,模板使用不同的語法來指出它存儲的數據類型。第四, vector類使用不同的語法來指定元素數。下面是一些示例:
#include <vector>
...
usinga namespace std;
vector<int> vi; //創建一個長度爲零的int型數組
int n;
cin >> n;
vector<double> vd(n); //創建一個大小爲n的double型數組
其中,vi是一個 vector對象,vd是一個 vector對象。由於 vector對象在插入或添加值時自動調整長度,因此可以將vi的初始長度設置爲零。但要調整長度,需要使用vector包中的各種方法。
一般而言,下面的聲明創建一個名爲vt的vector對象,它可存儲n_elem個類型爲type_Name的元素:
vector<typeName> vt(n_elem);
其中參數n_elem可以是整型常量,也可以是整型變量。
模板類array(C++11)
vector類的功能比數組強大,但付出的代價是效率稍低。如果需要的是長度固定的數組,使用數組是更佳的選擇,但代價是不那麼方便和安全。有鑑於此,C++11新增了模板類aray,它也位於名稱空間std中。與數組一樣,aray對象的長度也是固定的,也使用棧(靜態內存分配),而不是自由存儲區,因此其效率與數組相同,但更方便,更安全。要創建aray對象,需要包含頭文件array。array對象的創建語法與vector稍有不同:
#include <array>
...
using namespace std;
array<int, 5> ai; //創建一個大小爲5的array對象
array<double, 4> ad = {1.2, 2.1, 3.43, 4.3};
推而廣之,下面的聲名創建一個名爲arr的array的對象,它包含n_elem個類型爲typeName的元素:
```C++
array<typeName, n_elem> arr;
與創建veto對象不同的是,n_elem不能是變量,在C++11中,可將列表初始化用於vector和array對象,但在C++98中,不能對vector對象這樣做.
比較數組、vector對象和array對象
要了解數組、 vector對象和aray對象的相似和不同之處,最簡單的方式可能是看一個使用它們的簡單示例:
#include iostream>
include <vector> //STL C++98
#include <array> //C++11
int main()
{
using namespace std;
//C, original C++
double a1[4]={1.2,2.4,3.6,4,8};
//C++98sTL
vector<double> a2(4); // create vector with 4 element
// no simple way to initialize in C98
a2[0]=1.0/3.0;
a2[1]=1.0/5.0;
a2[2]=1.0/7.0;
a2[3]=1.0/9.0;
// C++11-- create and initialize array object
array<double,4> a3 = {3.14,2.72,1.62,1,41};
array<double, 4> a4;
a4=a3; //valid for array objects of same size
// use array notation
cout<<"a1[2]:"<<a1[2]<<"at"<<&a1[2]<<end1;
cout<<"a2[2]:"<<a2[2]<<"at"<<&a2[2l<<endl;
cout<<"a3[2]:"<<a[2]<<"at"<<&a3[2]<<endl;cout<<"a4[2]:"<<a4[2]<<"at"<<&a4[2]<end1
// misdeed
a1[-2]=20.2;
cout<<"a1[-2]:"<<a1[2]<<"at"<&a1[-2]<<endl;
cout<<"a3[2]:"<<a3[2l<<"at"<&a3[2]<<endl;cout<<"a4[2]:"<<a4[2]<<"at"c&a4[2<<endl;
ruturn 0;
}
//程序輸出
a1[2]:3,6 at 0x28cce8
a2[2]:0.142857 at 0xca0328
a3[2]:1.62 at 0x28ccc8
a4[2]:1.62 at 0x28cca8
a1[-2]:20.2 at 0x28ccc8
a3[2]:20.2 at 0x2BcccB
a4[2]:1.62 at 0x28ccaB
注意到無論是數組、 vector對象還是aray對象,都可使用標準數組表示法來訪問各個元素。其次,從地址可知,aray對象和數組存儲在相同的內存區域(即棧)中,而 vector對象存儲在另一個區域(自由存儲區或堆)中。第三,注意到可以將一個array對象賦給另一個aray對象:而對於數組,必須逐元素複製數據。
下面有一行代碼需要特別注意:
a1[-2] = 20.2;
這個索引將被轉換爲如下代碼:
*[a1-2] = 20.2;
其含義如下:找到a1指向的地方,向前移兩個 double元素,並將20.2存儲到目的地。也就是說將信息存儲到數組的外面。與C語言一樣,C++也不檢查這種超界錯誤。在這個示例中,這個位置位於aray對象a3中。其他編譯器可能將20.2放在a4中,甚至做出更糟糕的選擇。這表明數組的行爲是不安全的。