一、vector概述
vector是線性容器,元素按照線性順序排序,容器中元素存儲在一塊連續的內存中,類似與數組,不過vector可以自動增長或縮小存儲空間。
與數組相比:在自動處理容量的大小時會消耗更多的內存,當時vector可以提供和數組一樣的性能,並且可以很好的調整存儲空間的大小。
和其他標準的順序容器相比:vector可以更有效的訪問容器內元素,和在末尾添加、刪除元素;而在其他位置的添加刪除元素,vector不如其他順序容器。
注意:size()返回容器的大小,大小指的是當前容器中元素的個數,cacapacity()返回的是容器的容量,容量指的是已經分配的內存的大小。
二、vector的使用
1、初始化和遍歷
//三種遍歷方式
//1、下標
for(int i=0; i<vec.size(); i++){
cout << vec[i] << ", ";
}
cout << endl << "---------" << endl;
//2、迭代器
for(vector<int>::iterator it = vec.begin(); it != vec.end(); it++){
cout << *it << ", ";
}
cout << endl << "---------" << endl;
//3、for each
for(int temp : vec){
cout << temp << ", ";
}
其中,vec.begin()指的是vec中第一個元素的迭代器,vec.end()指的是最後一個元素的下一個位置。
2、vector的排序
兩種方式:1)如果存放的是自定義對象,則可以在類中實現<運算符,然後使用sort函數進行比較;2)自定義比較函數,在使用sort函數的時候,將比較函數當作參數傳入其中。其中,sort函數是算法中的函數,頭文件是algorithm。
3、查找
可以使用算法中的find函數,頭文件是algorithm。如果存在則返回迭代器,否則返回vector.end()。
4、刪除
三種方式:1)pop_back(),刪除最後一個元素;2)erase()刪除指定元素;3)clear(),刪除所有元素,清空。
erase()有兩種形式:
- iterator erase(iterator position)
- iterator erase(iterator first, iterator last)
使用erase的時候要注意迭代器失效的問題。
for(auto it = vec.begin(); it != vec.end(); it++){
if(*it == 3){
vec.erase(it);
}
}
此代碼是錯誤的,當刪除it的時候,it就變成了野指針,無法進行++操作的。
for(auto it = vec.begin(); it != vec.end(); it++){
if(*it == 3){
it = vec.erase(it);
}
}
此代碼也是錯誤的:1)無法刪除連續的3;2)當3位於vector的末尾,刪除的時候也會出錯(在vec.end()上執行了++操作)。
for(auto it = vec.begin(); it != vec.end(); ){
if(*it == 3){
it = vec.erase(it);
}else{
++it;
}
}
這纔是正確的刪除方式。
5、添加
有兩種方式:1)insert,是在指定位置添加元素;2)push_back,是在最後添加元素
insert有三種形式:
- iterator insert(iterator pos, const TYPE &val)//在pos前插入val,返回這個元素的迭代器
- void insert(iterator pos, size_type num, const TYPE &val)//在pos前插入num個val元素
- void insert(iterator pos, input_iterator start, input_iterator end)//在pos前,插入[start, end)區間中的元素
三、小技巧
1、使用reserve ()函數提前設定容量大小
vector支持隨機訪問,爲了提高效率,採用動態數組實現。在通過reserve函數來申請特定大小的內存空間的時候,總是按照指數邊界來增大其內部緩衝區的。當進行insert或者push_back操作時,如果空間不夠用,則會重新分配當前大小的1.5~2倍的新內存區,然後再把原來的內容複製過去。所以,當重新分配的操作發生時,其性能纔會下降。
所以,如果有大量的數據進行添加的時候,應當使用reserve()函數提前設定其容量大小,否則會出現多次容量擴大的操作,導致效率低下。
比如,如果要存儲1000個數據,可以這樣做:
vector<int> vec;
vec.reserve(1000);
for(int i = 0; i < 1000; i++)
vec.push_back(i)
2、使用“交換”來調整vector過剩空間
有一種方法來把它從曾經最大的容量減少到它現在需要的容量,這樣的方法常常被稱之爲“收縮到合適”(shrink to fit)。
該方法只需要一條語句:vector<int>(ivec).swap(ivec)。
vector<int>(ivec)表示建立一個臨時的vector,它是ivec的一份拷貝。但是vector的拷貝構造函數只分配拷貝元素所需要的內存,也就是說這個臨時的vector沒有多餘的空間。然後臨時的vector和ivec進行交換數據,但是ivec只有臨時變量的修正過的容量,而這個臨時變量則持有了ivec曾經沒有用到的容量。在這條語句的結尾處,臨時vector被銷燬,釋放之前ivec使用的內存,而相應的ivec收縮到合適大小。