vector容器类:
#include <vector>
std::vector<int> MyVector;
作为vector的元素,要求元素能够进行赋值和拷贝操作,即元素类型拥有赋值运算符和拷贝构造函数,
如果元素类型是用户自定义类型,operator=和拷贝构造函数可以是用户定义的,也可以是编译器自动
生成的。(注意编译器产生的有可能引发错误,例如类型的成员包含指针就有可能引起错误)。
vector的特征:
1.支持自由存取。
2.使用自由存取迭代器,因此可以使用STL的所有算法。(注:STL的有些算法只支持自由存取迭代器,
因此如果容器不支持自由存取,即容器使用的不是自由存取迭代器,则这些容器不能使用这些算法)
3.在末端追加和删除元素效率高。
大小和容量(size和capacity):
除了通用的size(),empty()和max_size()函数外,vector还拥有capacity()函数。
capacity()返回一个vector的实际内存中能够容纳的字符数(容量),如果超过了这个数目,这个vector
必须重新分配它的内存空间,将获取一块更大的空间。例如:如果你在container后面用push_back(),
安插元素,当安插的元素多于capacity()-size()时,这个vector的内存将会被重新分配。
重新分配将会增加vector的capacity(),size()和max_size不会改变,但会使指向此vector的任何迭代器
失效,因此应该避免重新分配。
max_size: 是这个container可能容纳的最大数目,是常量。
size:container现在存放的元素数量,相关函数:resize()
capacity:如果在size==capacity的情况下增加容器的元素,capacity就会变大,相关函数:reserve()
如果删除一个元素,size会变小,但是capacity不变。
避免重新分配的方法:
方法一:使用reserve函数。
std::vector<int> v; // create an empty vector
v.reserve (80); // reserve memory for 80 elements
方法二:
std::vector<T> v(5); // creates a vector and initializes it with five values
// (calls five times the default constructor of type T)
因为效率原因,我们应该使用方法一。
创建、拷贝、销毁操作:
vector<Elem> c
vector<Elem> c1(c2)
vector<Elem> c(n)
c.~vector<Elem>()
vector<Elem> c(n,elem)
vector<Elem> c(beg,end)
非修改操作(包括大小操作和比较操作):
c.size()
c.empty()
c.max_size()
capacity()
reserve()
c1 == c2
c1 != c2
c1 < c2
c1 > c2
c1 <= c2
c1 >= c2
reserve(n) 增加容量至n,提供的n不小于当前大小。
赋值操作:
c1 = c2
c.assign(n,value) 把n个值为value的元素赋给c
c.assign(beg,end) 把范围[beg,end)内的元素赋给c
c1.swap(c2)
swap(c1,c2)
元素访问操作:
c.at(idx) 返回索引号为idx的元素(如果索引号idx超出范围,抛出range error exception)。
c[idx] 返回索引号为idx的元素(无范围检查)。
c.front() 返回第一个元素(不会检查第一个元素是否存在)。
c.back() 返回最后一个元素(不会检查最后一个元素是否存在)。
因为c[idx]、c.front()和c.back()都没有进行相关的检查,一个范围错误将导致不确定行为。例如:
std::vector<Elem> coll; // empty!
coll [5] = elem; // RUNTIME ERROR ? undefined behavior
std::cout << coll. front (); // RUNTIME ERROR ? undefined behavior
对一个空容器调用[],front()和back()经常导致不确定行为,所以我们在调用[]时必须确保索引号是
有效的,在调用front()和back()时容器是非空的。
std::vector<Elem> coll; // empty!
if (coll.size() > 5) {
coll [5] = elem; // OK
}
if (!coll.empty()) {
cout << coll.front(); // OK
}
coll.at(5) = elem; // throws out_of_range exception
迭代器操作:
c.begin()
c.end()
c.rbegin()
c.rend()
迭代器一直保持有效,直到一个索引号更小的元素插入或移除或发生了重新分配导致容量(capacity)改变。
插入和移除元素操作:
对于使用STL插入和移除元素,必须确保参数是有效的,迭代器必须指向有效的位置,范围的开始位置不在
结束位置的后面,防止从空容器中移除元素。
插入和移除元素将使指向该位置(插入和移除的位置)以后的引用、指针和迭代器失效,如果一个插入操作
引起重新分配,它将使所有的引用、指针和迭代器无效。
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()增加,新元素通过默认构造函数创建。
c.resize(num,elem) 改变元素的数目为num,如果size()增加,新元素拷贝elem得到。
c.clear() 移除所有元素(使容器变为空)。
将vector用作普通数组:
对于vector容器类有下面的表达式成立:
&v[i] == &v[0] + i
其中v为vector容器类,定义如下:
std::vector<T> v;
下面看一个vector用作普通数组的例子:
std::vector<char> v;
v.resize(41); // 分配能容纳41个字符的空间,包括'/0'在内。
strcpy(&v[0], "hello, world"); // copy a C-string into the vector
printf("%s/n", &v[0]);
注意:不能将一个迭代器当作第一个元素的地址,迭代器是特别实现、有特殊含义的类型。
例如下面这样写是不对的:
printf("%s/n", v.begin()); // ERROR (might work, but not portable)
printf("%s/n", &v[0]); // OK
最后看一个总结的例子:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
//create empty vector for strings
vector<string> sentence;
//reserve memory for five elements to avoid reallocation
sentence.reserve(5);
//append some elements
sentence.push_back("Hello,");
sentence.push_back("how");
sentence.push_back("are");
sentence.push_back("you");
sentence.push_back("?");
//print elements separated with spaces
copy (sentence.begin(), sentence.end(),
ostream_iterator<string>(cout," "));
cout << endl;
//print ''technical data''
cout << " max_size(): " << sentence.max_size() << endl;
cout << " size(): " << sentence.size() << endl;
cout << " capacity(): " << sentence.capacity() << endl;
//swap second and fourth element
swap (sentence[1], sentence [3]);
//insert element "always" before element "?"
sentence.insert (find(sentence.begin(),sentence.end(),"?"),
"always");
//assign "!" to the last element
sentence.back() = "!";
//print elements separated with spaces
copy (sentence.begin(), sentence.end(),
ostream_iterator<string>(cout," "));
cout << endl;
//print "technical data" again
cout << " max_size(): " << sentence.max_size() << endl;
cout << " size(): " << sentence.size() << endl;
cout << " capacity(): " << sentence.capacity() << endl;
}
The output of the program might look like this:
Hello, how are you ?
max_size(): 268435455
size(): 5
capacity(): 5
Hello, you are how always !
max_size(): 268435455
size(): 6
capacity(): 10