vector 詳細用法 C++
使用STL的三個境界:能用,明理,能擴充套件。本文屬於第一個境界,如果結合了《STL原始碼解析》,則達到了第二個境界,如果專案中有需要,對STL進行了擴充套件則就達到了第三個境界!如果希望深刻理解vector的這些個成員函式,最好的辦法是詳細瞭解其內部實現,《STL原始碼解析》是個好途徑!當然,也可以直接看編譯器自帶的<vector>的原始碼。
vector是C++標準模板庫中的部分內容,vector之所以被認為是一個容器,是因為它能夠像容器一樣存放各種型別的物件,簡單地說,vector是一個能夠存放任意型別的動態陣列。
為了使用vector,必須包含標頭檔案<vector>。另,vector屬於std名稱空間,因此需要通過命名限定,可以有如下三種方式,後兩種方式更好,因為未引入的無關的內容。(依稀記的《Effective C++》的某個條款這個提過!)
using namespace std;
using namespace std::vector;
std::vector<int> vec;
現在以 std::vector<int> vec為例,描述相關函式的功能!
第一部分:
vec.begin()//指向迭代器中第一個元素。 vec.end()//指向迭代器中末端元素的下一個,指向一個不存在元素。 vec.push_back(elem) //在尾部加入一個數據。 vec.pop_back() //刪除最後一個數據。 vec.capacity() //vector可用空間的大小。 vec.size()//返回容器中資料個數。 vec.empty() //判斷容器是否為空。 vec.front() //傳回第一個資料。 vec.back() //傳回最後一個數據,不檢查這個資料是否存在。 vec.at(index) //傳回索引idx所指的資料,如果idx越界,丟擲out_of_range。 vec.clear() //移除容器中所有資料。 vec.erase(iterator) //刪除pos位置的資料,傳回下一個資料的位置。 vec.erase(begin,end) //刪除[beg,end)區間的資料,傳回下一個資料的位置。注意:begin和end為iterator vec.insert(position,elem) //在pos位置插入一個elem拷貝,傳回新資料位置。 vec.insert(position,n,elem) //在pos位置插入n個elem資料,無返回值。 vec.insert(position,begin,end) //在pos位置插入在[beg,end)區間的資料,無返回值。
以下程式碼驗證上述這些常用函式的功能:
#include<vector> #include<iostream> using namespace std; int main() { vector<int> vec(3,0); vector<int>::iterator iter; vector<int>::iterator begin=vec.begin(); vector<int>::iterator end=vec.end(); cout<<"vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t i=0; cout<<*iter<<","; i++; } cout<<endl; cout<<"size:"<<vec.size()<<endl; cout<<"capacity:"<<vec.capacity()<<endl; ////////////////////////////////////////////////// cout<<endl; vec.push_back(1); vec.push_back(2); begin=vec.begin(); end=vec.end(); cout<<"push back 1 and 2 based on above;vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t j=0; cout<<*iter<<","; j++; } cout<<endl; cout<<"size:"<<vec.size()<<endl; cout<<"capacity:"<<vec.capacity()<<endl; ////////////////////////////////////////////////// cout<<endl; vec.pop_back(); begin=vec.begin(); end=vec.end(); cout<<"pop one element based on above;vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t k=0; cout<<*iter<<","; k++; } cout<<endl; cout<<"size:"<<vec.size()<<endl; cout<<"capacity:"<<vec.capacity()<<endl; ///////////////////////////////////////////////// begin=vec.begin(); end=vec.end(); cout<<endl; if(vec.empty()) { cout<<"vec is empty"<<endl; } else { cout<<"vec is not empty"<<endl; } ///////////////////////////////////////////////// cout<<endl; cout<<"based on the above:"<<endl; cout<<" vec.front():"<<vec.front()<<endl; cout<<" vec.back():"<<vec.back()<<endl; begin=vec.begin(); end=vec.end(); cout<<" size:"<<vec.size()<<endl; cout<<" capacity:"<<vec.capacity()<<endl; cout<<"vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t l=0; cout<<*iter<<","; l++; } cout<<endl; //////////////////////////////////////////////////// cout<<endl; cout<<"call at(),based on the above:"<<endl; cout<<" vec.at():"<<vec.at(3)<<endl; begin=vec.begin(); end=vec.end(); cout<<" size:"<<vec.size()<<endl; cout<<" capacity:"<<vec.capacity()<<endl; cout<<"vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t m=0; cout<<*iter<<","; m++; } cout<<endl; ////////////////////////////////////////////////// cout<<endl; cout<<"call clear(),based on the above:"<<endl; vec.clear(); begin=vec.begin(); end=vec.end(); cout<<" size:"<<vec.size()<<endl; cout<<" capacity:"<<vec.capacity()<<endl; cout<<"vec:"; for(iter=begin; iter!=end; iter++) { static std::size_t m=0; cout<<*iter<<","; m++; } cout<<endl; ////////////////////////////////////////////////// cout<<endl; for(int i=1;i<8;i++) { vec.push_back(i); } cout<<"push_back 1,2,3,4,5,6,7 based on above;vec:"; begin=vec.begin(); end=vec.end(); for(iter=begin; iter!=end; iter++) { static std::size_t m=0; cout<<*iter<<","; m++; } //////////////////////////// cout<<endl; vec.erase(vec.begin()+2); cout<<"call vec.erase(3),vec:"; begin=vec.begin(); end=vec.end(); for(iter=begin; iter!=end; iter++) { static std::size_t m=0; cout<<*iter<<","; m++; } cout<<endl; cout<<" size:"<<vec.size()<<endl; cout<<" capacity:"<<vec.capacity()<<endl; ////////////////////////// cout<<endl; vec.erase(vec.begin()+1,vec.begin()+3); cout<<"call vec.erase(1,3),vec:"; begin=vec.begin(); end=vec.end(); for(iter=begin; iter!=end; iter++) { static std::size_t m=0; cout<<*iter<<","; m++; } cout<<endl; cout<<" size:"<<vec.size()<<endl; cout<<" capacity:"<<vec.capacity()<<endl; return 1;<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
輸出結果如下:
vector中v[i]與v.at(i)的區別:參見:http://www.cnblogs.com/zhuyf87/archive/2012/12/06/2805579.html
void f(vector<int> &v)
{
v[0]; // A
v.at[0]; // B
}
如果v非空,A行和B行沒有任何區別。如果v為空,B行會丟擲std::out_of_range異常,A行的行為未定義。
c++標準不要求vector<T>::operator[]進行下標越界檢查,原因是為了效率,總是強制下標越界檢查會增加程式的效能開銷。設計vector是用來代替內建陣列的,所以效率問題也應該考慮。不過使用operator[]就要自己承擔越界風險了。如果需要下標越界檢查,請使用at。
第二部分:
assign函式原型及功能:
void assign(const_iterator first,const_iterator last); //功能:將區間[first,last)的元素賦值到當前的vector中,當前vector會清除掉容器中之前的內容。
void assign(size_type n,const T& x = T()); //功能:賦n個值為x的元素到當前vector中,當前vector會清除掉容器中之前的內容。
以下函式驗證assign函式的功能:
#include <vector>
#include <iostream>
using namespace std;
int main( )
{
vector<int> v1, v2, v3;
vector<int>::iterator iter;
for(int i=10; i<60; i+=10)
{
v1.push_back(i);
}
v2.push_back(1);
v2.push_back(2);
cout << "v1 = " ;
for (iter = v1.begin(); iter != v1.end(); iter++)
{
cout << *iter << " ";
}
cout << endl;
cout << "v2 = ";
for (iter = v2.begin(); iter != v2.end(); iter++)
cout << *iter << " ";
cout << endl;
v1.assign(v2.begin(), v2.end());
cout << "v2 = ";
for (iter = v2.begin(); iter != v2.end(); iter++)
cout << *iter << " ";
cout << endl;
v3=v1;
v3.assign(4,3) ;
cout << "v3 = ";
for (iter = v3.begin(); iter != v3.end(); iter++)
cout << *iter << " ";
cout << endl;
return 0;
}
執行結果如下:第三部分:
vec.rbegin()//傳回一個vector的最後一個數據的指標。
vec.rend()// 傳回一個vector的第一個資料前一個位置的指標。?
驗證程式碼如下:#include <vector>
#include <iostream>
using namespace std;
int main( )
{
vector<int> v1, v2, v3;
vector<int>::iterator iter;
for(int i=10; i<60; i+=10)
{
v1.push_back(i);
}
v2.push_back(1);
v2.push_back(2);
cout << "v1 = " ;
for (iter = v1.begin(); iter != v1.end(); iter++)
{
cout << *iter << " ";
}
cout << endl;
cout << "v2 = ";
for (iter = v2.begin(); iter != v2.end(); iter++)
cout << *iter << " ";
cout << endl;
vector<int>::reverse_iterator r_iter;
cout << "v1 in reverse ";
for (r_iter = v1.rbegin(); r_iter != v1.rend(); r_iter++)
cout << *r_iter << " ";
cout << endl;
cout<<"v1.rbegin():"<<*v1.rbegin()<<endl;
cout<<"v1.rbegin():"<<(*(v1.rbegin()--))<<endl;
cout<<"v1.rend()--:"<<*(v1.rend()--)<<endl;
cout<<"v1.rend()++:"<<*(v1.rend()++)<<endl;
return 0;
}
輸出結果為:
此處有個疑問:對(*(v1.rbegin()++))、(*(v1.begin()++))、(*(v1.rbegin()--))、(*(v1.begin()--))均沒達到預期,需要看下其內部究竟是怎麼實現的!
另外,注意:企圖直接列印迭代器,編譯是通不過的!eg:cout<< v1.begin();
第四部分:
vec.resize(num)//重新指定vector的長度。
vec.resize(num,value)//重新指定vector的長度。並設定新增的元素的值
當需要以vec[size+1]=vec[j];的方式對超過vector的size賦值時,都需要先呼叫下resize()函式,如果直接對超出vector.size()的位置賦值,編譯不能通過!
如上所示,一種是僅僅設定size,另一種即設定size也設定value;其實resize函式就是重新設定finish指標。如果在呼叫resize函式時,發現vector沒有剩餘的空間了,則會以當前的size為基礎,申請開闢2倍的空間。(開闢空間,拷貝,釋放原有空間的過程)
第五部分:
vec.swap(vec1)//
swap(vec,vec1)//
#include<vector>
#include<iostream>
using namespace std;
int main()
{
vector<int> vec(3,0);
vector<int>::iterator iter;
vector<int>::iterator begin=vec.begin();
vector<int>::iterator end=vec.end();
cout<<"vec:";
for(iter=begin; iter!=end; iter++)
{
static std::size_t i=0;
cout<<*iter<<",";
i++;
}
cout<<endl;
vec.push_back(7);
cout<<"size:"<<vec.size()<<endl;
cout<<"capacity:"<<vec.capacity()<<endl;
vector<int>(vec).swap(vec);
cout<<"vector<int>(vec)-swap-capacity:"<<vec.capacity()<<endl;
cout<<"vector<int>(vec)-swap-size:"<<vec.size()<<endl;
{
vector<int> temp(vec);
temp.swap(vec);
cout<<"temp-swap-capacity:"<<vec.capacity()<<endl;
cout<<"temp-swap-size:"<<vec.size()<<endl;
}
vector<int>().swap(vec);
cout<<"vector<int>()-swap-capacity:"<<vec.capacity()<<endl;
cout<<"vector<int>()-swap-size:"<<vec.size()<<endl;
return 1;
}
輸出結果為:#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
vector<int> vec(3,0);
vector<int>::iterator iter;
vector<int>::iterator begin=vec.begin();
vector<int>::iterator end=vec.end();
cout<<"vec:";
for(iter=begin; iter!=end; iter++)
{
static std::size_t i=0;
cout<<*iter<<",";
i++;
}
cout<<endl;
vec.push_back(7);
cout<<"vec size:"<<vec.size()<<endl;
cout<<"vec capacity:"<<vec.capacity()<<endl;
vector<int> vec1(3,1);
vec1.push_back(6);
cout<<"vec1 size:"<<vec1.size()<<endl;
cout<<"vec1 capacity:"<<vec1.capacity()<<endl;
swap(vec,vec1);
begin=vec.begin();
end=vec.end();
cout<<"after swap vec:";
for(iter=begin; iter!=end; iter++)
{
cout<<*iter<<",";
}
cout<<"vec size after swap():"<<vec.size()<<endl;
cout<<"vec capacity after swap():"<<vec.capacity()<<endl;
begin=vec1.begin();
end=vec1.end();
cout<<"after swap vec1:";
for(iter=begin; iter!=end; iter++)
{
cout<<*iter<<",";
}
cout<<"vec1 size after swap():"<<vec1.size()<<endl;
cout<<"vec1 capacity after swap():"<<vec1.capacity()<<endl;
return 0;
}
輸出結果為:該結果表明<algorithm>中的函式swap(),只是交換兩個vector中的內容,其原本的size和capacity均不做改變!
vec.reserve()//設定capacity的值,如果小於原本的capacity的值則保持為原本的capacity的值。
以下為顯而易見的操作:
operator[]://此函式返回的是容器中指定位置的一個引用。
operattor*://指標的取址操作
若干種建立方式(vector的建構函式)
vector<type> vec
vector<type> vec(vec1)
vector<type> vec=vec1
vector<type> vec(n)
vector<type> vec(n,elem)
vector<type> vec(begin,end)
vector<type> vec{a,b,c,……}
vector<type> vec={a,b,c,……}