一、概述
vector構造出一個動態數組,本身是將元素置於動態數組中加以管理的抽象概念。使用vector之前必須含入頭文件<vector>,vector是一個定義於namespace std內的template
namespace std {
template <class T,
class Allocator = allocator<T> >
class vector;
}
vector將元素複製到內部動態數組中,vector的迭代器是隨機存取迭代器,所以支持隨機存取。在末端添加、刪除元素時,vector的性能相當好。但是在前端或者中部安插或刪除元素,性能就不怎麼好了,因爲操作點之後的每一個數據都要移動到另一個位置。vector性能優異的重要原因就是配置比其容納元素所需更多的內存。vector的容量很重要:
1. 一旦內存重新配置,和vector相關的引用、指針、迭代器都會失效;
2. 內存重新配置很耗時間。
二、vector的內部結構
vector類內通過三個保護成員的迭代器變量維護內存空間的使用:
template <class T, class Alloc = alloc>
class vector {
//省略其他成員
protected:
iterator start; //表示目前使用空間的頭
iterator finish; //表示目前使用空間的尾
iterator end_of_storage; //表示目前可用空間的尾
}
新增加元素時,如果超過當時容量,則容量會擴充至兩倍。如果兩倍容量仍然不夠,就擴張至足夠大的容量。所謂動態增加大小,並不是在原空間之後接續新空間(因爲無法保證原空間之後有可用空間),而是以原大小的兩倍另外配置一塊較大的空間,然後將原空間內容拷貝過來,然後在原內容之後構造新元素,釋放原空間。一旦引起空間重新配置,指向原空間的所有迭代器就失效了!
三、vector的操作函數
1. 構造、拷貝和析構
操作 | 效果 |
---|---|
vector<Elem> c | 產生一個存放Elem類型元素的空vector |
vector<Elem> c1(c2) | 產生一個與c2同型的vector,每個元素都被複制 |
vector<Elem> c(n) | 產生一個含有n個元素,以default構造函數產生元素的vector |
vector<Elem> c(n,elem) | 產生一個含有n個elem元素的vector |
vector<Elem> c(beg,end) | 產生一個以區間[beg,end]內元素爲初值的vector |
c.~vector<Elem>() | 銷燬所有元素,釋放內存 |
2. 非變動性操作
操作 | 效果 |
---|---|
c.size() | 返回元素個數。 |
c.empty() | 判斷容器大小是否爲0。 |
c.max_size() | 返回整個內存空間可容納元素最大數量 |
c.capacity() | 返回重新分配空間前容器所能容納的元素最大數量 |
c.reserve() | 如果容量不足則擴大之 |
c1 == c2 | 判斷c1是否等於c2 |
c1 != c2 | 判斷c1是否不等於c2 |
c1 < c2 | 判斷c1是否小於c2 |
c1 > c2 | 判斷c1是否大於c2 |
c1 <= c2 | 判斷c1是否小於等於c2 |
c1 >= c2 | 判斷c1是否大於等於c2 |
3. 賦值操作
操作 | 效果 |
---|---|
c1 = c2 | 將c2的全部元素賦值給c1。 |
c.assign(n,elem) | 將elem的n個拷貝賦值給c。 |
c.assign(beg,end) | 將區間[beg,end]的元素賦值給c |
c1.swap(c2) | 將c1和c2元素互換 |
swap(c1,c2) | 同上,此爲全局函數 |
4. 元素存取操作
按照C和C++的慣例,第一元素的索引爲0,最後一個元素的索引爲size()-1。
操作 | 效果 |
---|---|
c.at(idx) | 返回索引位置idx處的元素,如果idx越界,拋出out_of_range異常 |
c[idx] | 返回索引位置idx處的元素,不進行範圍檢查 |
c.front() | 返回第一個元素,不檢查元素是否存在 |
c.back() | 返回最後一個元素,不檢查元素是否存在 |
5. 迭代器函數
操作 | 效果 |
---|---|
c.begin() | 返回一個隨機存取迭代器,指向第一個元素 |
c.end() | 返回一個隨機存取迭代器,指向最後一個元素的下一位置 |
c.rbegin() | 返回一個逆向迭代器,指向逆向迭代的第一個元素 |
c.rend() | 返回一個逆向迭代器,指向逆向迭代的最後元素的下一位置 |
6. 安插和移除元素
操作 | 效果 |
---|---|
c.insert(pos,elem) | 在pos位置插入一個elem副本,返回新元素的位置 |
c.insert(pos,n,elem) | 在pos位置插入n個elem副本,無返回值 |
c.insert(pos,beg,end) | 在pos位置插入區間[beg,end]內的元素,無返回值 |
c.push_back(elem) | 在尾部添加一個elem的副本 |
c.pop_back() | 移除最後一個元素,不回傳 |
c.erase(pos) | 移除pos位置所指元素,返回下一元素的位置 |
c.erase(beg,end) | 移除區間[beg,end]內的元素,返回下一元素的位置 |
c.resize(num) | 將大小改爲num。如果size增長了,新增大小以default構造函數產生出來 |
c.resize(num,elem) | 將大小改爲num。如果size增長了,新增大小以elem副本產生出來 |
c.clear() | 移除所有元素,將容器清空 |
如果要移除與某值相等的所有元素,可以這麼做:
std::vector<Elem> coll;
'''
// remove all elements with value val
std::vector<Elem>::iterator pos;
coll.erase(remove(coll.begin(),coll.end(),val), coll.end());
如果要移除與某值相等的第一個元素,可以這麼做:
std::vector<Elem> coll;
'''
// remove first element with value val
std::vector<Elem>::iterator pos;
pos = find(coll.begin(),coll.end(),val);
if (pos != coll.end()) {
coll.erase(pos);
}
四、Class vector<bool>
C++標準程序庫專門爲bool型的vector設計了一個特殊版本,目的是獲取一個優化的vector。其耗用空間遠遠小於一般vector。一般vector會爲每個元素至少分配一個byte空間,而vector<bool>內部只會用一個bit來存儲一個元素。不過C++的最小尋址單元通常以byte爲單位,因此vector<bool>::iterator並不返回真正的隨機存取迭代器。此外vector<bool>會比一般vector慢一點,因爲所有元素操作都轉化爲位操作。因爲vector<bool>的大小可以動態改變,所以可以作爲bitfield(位域),由此可以添加或刪除bits。若需要靜態大小的bitfield,應當使用bitset。
vector<bool>的特殊操作
操作 | 效果 |
---|---|
c.flip() | 將所有bool元素取反值 |
m[idx].flip() | 將索引idx位置處的bit元素取反值 |
m[idx] = val | 令索引idx位置處的bit元素值爲val |
m[idx1] = m[idx2] | 令索引idx1的bit元素值爲索引idx2的bit元素值 |
五、程序示例
vector的使用示例
//example of vector
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
vector<string> sentence;
sentence.reserve(5);
sentence.push_back("Hello,");
sentence.push_back("how");
sentence.push_back("are");
sentence.push_back("you");
sentence.push_back("?");
copy(sentence.begin(), sentence.end(),
ostream_iterator<string>(cout, " "));
cout << endl;
//max_size()返回當前整個內存空間可以容納string類型數據總量
cout << "max_size(): " << sentence.max_size() << endl;
cout << "size(): " << sentence.size() << endl;
cout << "capacity(): " << sentence.capacity() << endl;
swap(sentence[1], sentence[3]);
sentence.insert(find(sentence.begin(), sentence.end(), "?"),
"always");
sentence.back() = "!";
copy(sentence.begin(), sentence.end(),
ostream_iterator<string>(cout, " "));
cout << endl;
cout << "max_size(): " << sentence.max_size() << endl;
cout << "size(): " << sentence.size() << endl;
cout << "capacity(): " << sentence.capacity() << endl;
return 0;
}
輸出結果:
vector<bool>的使用示例
#include<vector>
#include<iostream>
#include<algorithm>
#include<iterator>
using namespace std;
int main()
{
vector<bool> vec1;
vector<int> vec2;
cout << vec1.max_size() << endl;
cout << vec2.max_size() << endl;
vec1.push_back(true);
vec1.push_back(1);
vec1.push_back(false);
vec1.push_back(0);
cout << "vector<bool>:";
copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
cout << endl;
vec1.flip(); //所有位置取反
vec1.at(0) = 1;
cout << "vector<bool>:";
copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
cout << endl;
vec1[1] = vec1[0];
cout << "vector<bool>:";
copy(vec1.begin(), vec1.end(), ostream_iterator<bool>(cout, " "));
cout << endl;
cout << "vec1.size:" << vec1.size() << ", " << "vec1.capacity:" << vec1.capacity() << endl;
cout << "sizeof vec1:" << sizeof(vec1) << endl; //24
vec1.push_back(false);
vec1.push_back(0);
cout << "sizeof vec1:" << sizeof(vec1) << endl; //24,說明與元素個數無關,僅與其內部結構相關
return 0;
}
輸出結果: