一、概述
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;
}
输出结果: