1. 程式人生 > 其它 >二維vector可以轉二維陣列使用嗎?

二維vector可以轉二維陣列使用嗎?

技術標籤:Cc++

前言

    由於vector過載了下標運算子,且vector所儲存的資料是連續儲存,因此我們可以將vector引數直接當作一維陣列來使用,但二維vector能否直接轉換成二維陣列來使用呢?
    不可以。

vector轉一維陣列

    首先,參考vector轉一維陣列的情況:

using std::vector;

template <typename T>
T *vector2array(vector<T> v)
{
    return (T *)&v[0];
}

    再來看看vector的記憶體佔用:

void sizeofvector
() { vector<int> v; vector< vector<int> > vv; cout<<"==1==\nsizeof(vv): "<<sizeof(vector< vector<int> >)<<" "<<sizeof(vv)<<endl; cout<<"sizeof(v): "<<sizeof(vector<int>)<<
" "<<sizeof(v)<<endl; for(int i(0); i < 100; i++) v.push_back(i); for(int i(0); i < 10; i++) vv.push_back(v); cout<<"==2==\nsizeof(vv) = "<<sizeof(vector< vector<int> >)<<" "<<sizeof(vv)<<
endl; cout<<"sizeof(v) = "<<sizeof(vector<int>)<<" "<<sizeof(v)<<endl; } // Result: // ==1== // sizeof(vv): 12 12 // sizeof(v): 12 12 // ==2== // sizeof(vv) = 12 12 // sizeof(v) = 12 12

    可見,雖然vector也具有和陣列“通過下標隨機訪問”一樣的特性,但vector是通過過載運算子"[]"來實現的,訪問記憶體的方式和陣列本質上並不相同。
    vector和陣列的訪問方式區別如下:
vector vs array
    vector直接當作一維陣列使用時,實際上“&v[0]”取的是data_ptr指向的記憶體區的首地址,而非vector本身的首地址。

二維vector vs. 二維陣列

    同樣的,二維vector也可以和二維陣列一樣通過"a[][]"的形式來實現,但需要注意它們首地址的區別:

    int **a[5][5];
    int *ptr = &a[0][0];
    vector<int> v;
    vector< vector<int> > vv;

    v.push_back(1); v.push_back(1); v.push_back(1); v.push_back(1);
    vv.push_back(v);vv.push_back(v);vv.push_back(v);vv.push_back(v);

    cout<<"&vv[0]       = "<<std::hex<<&vv[0]<<endl;    //0xeb0e18
    cout<<"&vv[0][0]    = "<<std::hex<<&vv[0][0]<<endl; //0xeb0dc8
    cout<<"&aa[0]       = "<<std::hex<<&aa[0]<<endl;    //0x63fe58
    cout<<"&aa[0][0]    = "<<std::hex<<&aa[0][0]<<endl; //0x63fe58

    這是因為,二維vector的資料儲存區(連續空間)儲存的是成員vector,而&vv[0]則是“所有成員vector連續儲存的空間”的首地址。通過“vv[x]”可以隨機訪問到某個成員vector,而成員vector又可以進一步通過"[]“運算子訪問成員vector的資料區域,因此二維vector同樣可以通過”[][]"的方式來訪問資料,這一點與二維陣列相同。只不過,二維vector儲存的資料並非連續。

結論

    1、二維陣列所有成員連續儲存在某個記憶體,二維vector不是;
    2、兩者都可以通過"[][]"訪問資料,但二維陣列每行列數必須相同,且作形參傳遞時必須宣告每行的列數;
    3、二維陣列可以降維訪問,二維vector不支援;

/*二維陣列的連續儲存*/
cout<<std::hex<<"&aa[1][3] "<<&aa[1][3]<<" &aa[2][0] "<<&aa[2][0]<<endl;
// &aa[1][3] 0x63fe70 &aa[2][0] 0x63fe74

/*二維vector的非連續儲存*/
cout<<std::hex<<"&vv[1][3] "<<&vv[1][3]<<" &vv[2][0] "<<&vv[2][0]<<endl;
// &vv[1][3] 0x9b0e0c &vv[2][0] 0x9b0d90

/*二維陣列的降維訪問*/
ptr = &aa[0][0];
for(int r(0); r < 4; r++)
    for(int w(0); w < 4; w++){
        cout<<std::dec<<"&aa["<<r<<"]["<<w<<"] "<<std::hex<<&aa[r][w] \
            <<" &ptr["<<r<<"*4 + "<<w<<"] "<<&ptr[r*4+w]<<endl;
    }
// &aa[1][1] 0x63fe60 &ptr[1*4 + 1] 0x63fe60
// &aa[3][2] 0x63fe84 &ptr[3*4 + 2] 0x63fe84

/*二維vector的降維訪問*/
ptr = &vv[0][0];
for(int r(0); r < 4; r++)
    for(int w(0); w < 4; w++){
        cout<<std::dec<<"&vv["<<r<<"]["<<w<<"] "<<std::hex<<&vv[r][w]<<" &ptr["<<r<<"*4 + "<<w<<"] "<<&ptr[r*4+w]<<endl;
    }
// &vv[1][1] 0xf60e04 &ptr[1*4 + 1] 0xf60ddc
// &vv[3][2] 0xf60de8 &ptr[3*4 + 2] 0xf60e00

二維vector訪問機制如圖:
double vector