二維vector可以轉二維陣列使用嗎?
阿新 • • 發佈:2020-12-17
前言
由於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直接當作一維陣列使用時,實際上“&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訪問機制如圖: