一、容器vector
使用vector必須包含頭文件<vector>:
#include<vector>
型別vector是一個定義於namespace std內的template:
[cpp]
template<class _Ty,
class _Ax = allocator<_Ty> >
template<class _Ty,
class _Ax = allocator<_Ty> >第二個參數定義內存模型。我們一般采用默認的內存模型。
二、vector的功能
vector模塑出一個動態數組。vector將其元復制到內部的動態數組中。元素之間總是存在某種順序,它是一種有序群集。支持隨即存取。它的迭代器是隨機存取迭代器,所以對任何一個STL算法都奏效。
向vector添加一個元素或者刪除其中的一個元素,其後的所有元素都要移動位置,每一次移動都要調用賦值操作符。所以,在末端添加或刪除元素,性能很好。但是在前段或者中部的話,性能較差。
vector優異性能的秘訣之一是它配置比其所容納的元素所需更多的內存。我們需要了解大小和容量的關系。
函數size()可以返回vector的大小,即vector中實際元素的個數。
而capacity()返回容量,是當前的vector所實際能夠容納的元素的數量。它應該總是大於或者等於vector的大小。如果需要向vector中放置比capacity更多的元素,則需要重新配置內部存儲器。vector的容量也會隨之增長。看下面的示例代碼:
[cpp]
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
vector<string> sentence(1);
cout << "max_size():" << sentence.max_size() << endl;
cout << "size():" << sentence.size() << endl;
cout << "capacity():" << sentence.capacity() << endl;
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;
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;
}
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
vector<string> sentence(1);
cout << "max_size():" << sentence.max_size() << endl;
cout << "size():" << sentence.size() << endl;
cout << "capacity():" << sentence.capacity() << endl;
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;
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;
}運行結果:
在程序中,當再次向vector插入元素時,由於vector的容量不夠,所以引起了內存的重新分配。但是capacity()的結果與實作版本有關,max_size也是。
vector的容量十分重要,是因為:
1、一旦內存重新配置,與之相關的所有的reference、pointers、iterators都會失效。
2、內存配置很費時。
解決這個問題的方法有:
1、可以使用reserve()保留適當容量,減少重新配置內存的次數。示例代碼:
[cpp]
vector<string> sentence(1);
sentence.reserve(50);
vector<string> sentence(1);
sentence.reserve(50);2、在初始化期間向構造函數傳遞附加參數,構造出足夠的空間。
[cpp]
vector<T> v(5);
vector<T> v(5);當然,這種元素的型別必須提供默認構造函數。但是如果元素的型別比較復雜,初始化操作也很耗時。如果只是為了保留足夠的內存,使用方法1較好。
注意:reserve不能縮減vector的容量。由此,我們可以知道,即使刪除元素,其reference、pointers、iterators也會繼續有效,指向動作發生前的位置。
但是插入操作可能使reference、pointers、iterators失效(因為可能會導致重新配置空間)。
使用swap函數可以縮減vector容量。因為兩個vector交換內容後,他們的容量也會互換。
1、
[cpp]
template<class T>
void shrinkCapacity(vector<T> &v)
{
vector<T> tmp(v);
v.swap(tmp);
}
template<class T>
void shrinkCapacity(vector<T> &v)
{
vector<T> tmp(v);
v.swap(tmp);
}2、
[cpp]
vector<T>(v).swap(v);
vector<T>(v).swap(v);上面兩種方法等價。 www.2cto.com
都是先構造出一個臨時vector對象,以v的元素進行初始化,再與v進行交換。需要注意的是:臨時對象一般都是精確分配實際所需的內存。所以能夠起到減小vector容量的效果。
三、vector的操作函數
所有的構造函數和析構函數如下:
非變動性操作:
賦值操作:
上述操作進行的是將新元素賦值給vector,並將舊元素全部移除!示例代碼:
[cpp]
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
vector<string> sentence(1);
cout << "max_size():" << sentence.max_size() << endl;
cout << "size():" << sentence.size() << endl;
cout << "capacity():" << sentence.capacity() << endl;
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;
sentence.assign(3,"new");
copy(sentence.begin(),sentence.end(),
ostream_iterator<string>(cout," "));
cout << endl;
}
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
vector<string> sentence(1);
cout << "max_size():" << sentence.max_size() << endl;
cout << "size():" << sentence.size() << endl;
cout << "capacity():" << sentence.capacity() << endl;
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;
sentence.assign(3,"new");
copy(sentence.begin(),sentence.end(),
ostream_iterator<string>(cout," "));
cout << endl;
}運行結果:
可以看出原來的元素全部被刪除了。
元素存取
在這幾個函數中,唯一進行下標檢查的是at函數。
因此,在調用operator[]的時候,必須心理清楚索引是否是有效的。
迭代器相關函數
迭代器失效的兩種情況是:
1、在一個較小的位置上刪除或者是移動元素。
2、由於容量的變換引起內存重新分配。
插入和移除元素
插入和移除元素,都會使“作用點”之後的各元素的reference、pointers、iterators失效。插入操作還可能引發內存重新分配,那麼該容器上的所有的reference、pointers、iterators都會失效。
四、把vector當做一般數組使用
現在的C++標准保證vector的元素必須分布於連續空間中。對於vector中的一個合法索引,滿足下列表達式:
&v[i] = &v[0] + i;
我們必須保證vector能夠容納所有數據。如果使用的是C-String,記住最後有個'\0'。
只要我們需要一個元素型別為T的數組,就可以采用vector<T>,然後傳遞第一個元素的地址給它。
注意:千萬不要把迭代器當做第一元素的地址來傳遞。因為vector迭代器是由實作版本定義的,不一定是一個一般指針。
[cpp]
printf("%s",v.begin());//ERROR(might work,but not portable)
printf("%s",&v[0]);//OK
printf("%s",v.begin());//ERROR(might work,but not portable)
printf("%s",&v[0]);//OK