1. 程式人生 > >向量和陣列易錯知識點

向量和陣列易錯知識點

vector的初始化

vector可以用初始化列表完成物件的初始化,但有兩處容易想當然,造成錯誤的理解!

vector<string> v1 {"hi"}; //ok
vector<string> v2 ("hi"); //error,無對應的建構函式

vector<string> v3(10,"hi"); //ok,v3有10個"hi"
vector<string> v4{10,"hi"}; //ok,與上一句一樣
//!注意:如果初始化時使用了花括號的形式但是提供的值又不能用來列表初始化,就要考慮用這樣的值來構造vector物件了!這裡主要是因為int型無法隱式的轉換成string型別;再看下面的例子:
vector<char> c1{10,'a'}; //ok,含兩個字元

陣列的初始化

當定義陣列時,字串陣列和數值類陣列的預設初始化不同,要特別注意:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int myint[10];  //函式體外,預設初始化為0
string s1[10];  //初始化為空串
int main(int argc, char *argv[])
{
    int myint2[10];  //函式體內,未顯式初始化,則其值是未知的
string s2[10]; //初始化為空串 for(auto i:myint2) cout<<i<<"\t"; cout<<"\n======================================================\n\n"; for(auto i:myint) cout<<i<<"\t"; return 0; }

所以最好在使用的時候才定義,定義時最好初始化。

複雜的陣列宣告

int *ptrs[10];  //ptrs是含有10個整形指標的陣列
int &refs[10] = /*?*/ //error!不存在引用的陣列 int (*Parray)[10] = &arr; //Parray指向一個含有10個整數的陣列 int (&arrRef)[10] = arr; //arrRef引用一個含10個整數的陣列

Tips:

  • 預設情況下,型別修飾符應從右往左依次繫結
  • 對陣列來說,由內向外的與閱讀順序更易讓人理解:首先(*Parray)意味Parray著是一個指標,接下來觀察右邊,知道Parray指向一個大小為10的陣列,最後觀察左邊,知道陣列中的元素型別是int!

指標和陣列

陣列的名字其實是其首元素的指標,但在對陣列名使用auto和decltype時,兩者區別很大!

int ia[] = {0,1,2,3,4,5,6,7,8,9};  //ia是一個含10個整數的陣列
auto ia2(ia);  //ia2是一個整形指標,指向ia的第一個元素
decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};  //ia3是一個含10個整數的陣列!
ia[3] = i;  //為ia3的一個元素賦值

要特別注意上面auto和decltype的區別

多維陣列

多維陣列其實就是陣列的陣列,int arr[10][20][30]={0};按照上文的方法由內向外讀,首先array是個大小為10的陣列,他的每個元素都是大小為20的陣列,這些陣列的元素又都是含有30個整數的陣列。
多維陣列可以用花括號初始化:

int ia[3][4] = { {0,1,2,3}, {4,5,6,7}, {8,9,10,11} }; 
int ia2[3][4] = { {0}, {1}, {2} };  //將行首元素分別初始化為0,1,2

練習:
編寫三個不同版本的程式,使其輸出ia的元素:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main(int argc, char *argv[])
{
    int array[3][4]= {0,1,2,3,4,5,6,7,8,9,10,11};
    // VERSON 1 : using range for
    cout<<"\nVERSON 1 : using range for\n";
    for(int (&p)[4] : array)        //必須用& 引用
    {
        for(int i : p)
            cout<<i<<"\t";
        cout<<endl;
    }

    //VERSON 2: using traditional for & []
    cout<<"\nVERSON 2 : using traditional for & []\n";
    for (int i = 0; i<3;i++)
    {
        for(int j = 0; j<4; j++)
            cout<<array[i][j]<<"\t";
        cout<<endl;

    //VERSON 3: using traditional for & pointors
    cout<<"\nVERSON 3: using traditional for & pointors\n";
    for (int (*p)[4]=array;p!=array+3;p++)
    {
        for(int *j = *p; j!=(*p)+4; j++)
            cout<<*j<<"\t";
        cout<<endl;
    }
    return 0;
}