本身是一个基于dynamic arrray的一个抽象概念
使用前必须包含#include
namespce std{
template>
class vector;
}
第一个参数为任意类型,第二个参数用以定义内存模型,默认参数为C++标准库提供的allocator
基于一种动态数组的概念,因此元素之间总是存在着一定的顺序,所以vector是一种有序集合
基于有序集合,在vector末尾添加或者删除元素的效率都相当好,但是在除末尾以外的位置修改元素效率就不怎么样了(因为要维护每一个元素的相对位置,修改一个要改变其后面所有元素的位置)
类似于数组的成员下标,vector支持随机访问迭代器,适用于所有的STL算法
概念理解:大小是指实际元素的多少,容量是指总共所能够元素的大小即size<=capacity
对于操作大小和容量的函数:
size() //返回实际元素的多少、
empty() //返回容器是否为空的判断
capacity() //返回容器能够储存的元素量
Vector的容器之所以重要,有两个原因
一旦内存重新分配,vector容器中的所有reference,pointer,iterator都会失效
内存分配很耗费时间
两个解决容量分配时间过多的方法:
通过调用reserve()函数保留适当容量
std::vector v;
v.reserve(80);
通过在初始化期间传入额外实参,构建足够的内存空间
std::vectorv(10);
这两种方法的区别:通过调用reserve()函数得到的就是为了保留足够空间而已,但通过初始化时来分配空间必须要额外需要一个对应T类型的default构造函数
如果要缩减容量以符合当前元素个数,可以使用C++11引入的shrink_to_fit()函数
v.shrink_to_fit();
注:该要求不具有强制力,因此你不能够期望之后的v.capacity()==v.size()会获得true
vectorc; //默认构造函数,产生一个空的容器
vectorc(c2); //拷贝构造函数,成为c2的一个拷贝
vectorc=c2; //拷贝构造函数,成为c2的一个拷贝
vectorc(rv); //移动构造函数,取rv的内容作为c的内容
vectorc=rv; //移动构造函数,取rv的内容作为c的内容
vectorc(n); //通过其中T类型的default构造函数构造一个大小为n的vector
vectorc(n,elem); //建立一个大小为n的容器,每一个内容都是elem
vectorc(begin,end); //通过[begin,end)内的内容构造一个容器
vectorc(initlist); //通过初始化列表来初始化容器
vectorc=initlist; //于上种方法相似
c.~vector(); //销毁所有元素释放内存
c.empty()
c.size()
c.capacity()
c.reserve(num)
c.shrink_to_fit()
c1==c2 //对每个元素执行逻辑判断(即元素要重载逻辑判断)
c1!=c2
c1c2
c=c2 //拷贝
c=rv //以移动赋值的方式赋值到c种
c=initlist
c.assign(n.elem)
c.assign(beg,end)
c.assign(initlist)
c1.swap(c2)
swap(c1,c2)
注:所有赋值操作都有可能调用元素类型的default构造函数,copy构造函数,assignment操作符或析构函数
欲访问vector的所有元素,你必须使用 range-base for循环,特定的操作函数或迭代器
注:对于以下操作函数,都是返回元素的reference1
c[idx] 返回下标为idx的元素(不执行范围检查)
c.at(idx) 返回下标为idx的元素(执行范围检查) 越界时抛出out_of_range的异常
c.front() 返回第一元素
c.back() 返回末尾元素
如果对一个空的vector调用operator[],front(),back()会有不明确的行为,因此调用前三者必须要确保访问有效
c.begin() //返回一个指向首处迭代器
c.cbegin() //返回一个const迭代器
c.end() //返回一个指向末尾下一个位置的迭代器
c.cend() //返回一个指向末尾下一个位置的const迭代器
c.rbegin() //返回一个reverse迭代器,指向末尾的下一个位置
c.rend() //返回一个reverse迭代器,指向首处的位置
c.crend() //返回一个const reverse迭代器,指向首处的位置
c.crbegin() //返回一个const reverse迭代器,指向末尾的下一个位置
注:以下两种情况迭代器会失效、
在一个较小索引位置上安插或移除元素(在其前方的元素全部失效)
由于容量变化而引起的内存重新分配
c.pop_back() //移除末尾元素,但不返回它(要保证容器非空)
c.push_back(elem) //附加一个elem的拷贝于末尾
c.insert(pos,elem) //在pos前的位置插入elem的拷贝,并返回新元素的位置
c.insert(pos,n,elem) //在pos前的位置插入n个elem的拷贝,返回第一个新元素的位置
c.insert(pos,begin,end) //在pos前的位置插入[beign,end)的拷贝,返回第一个新元素的位置
c.insert(pos,initlist) //在pos前的位置插入initlist的拷贝,返回第一个新元素的位置
c.emplace(pos,args...) //在pos前的位置插入以args为初值构造的元素,返回第一个新元素的位置
c.emplace_back(args...) //附加一个以args为初值的元素构造于末尾
c.erase(pos) //移除pos上的元素,返回下一个元素的位置
c.erase(begin,end) //移除[begin,end)区间上的元素,返回下一个元素的位置
c.resize(num) //将元素数量变为num,如果size()变大,那么则需要内置元素有default构造函数
c.resize(num,elem) //将元素数量变为num,如果size()变大,那么元素则为elem的拷贝
c.clear() //清空容器
关于效能在以下情况下预期安插动作和移除动作会比较快些
在容器末尾安插或移除元素
容量一开始就足够大
一次性安插多个元素相对于多次安插单个元素来的快
由于对于C++11标准并没有提供删除指定值的的元素,以下语句提供了两种删除指定元素的方法
std::vectorcoll;
coll.erase(remove(coll.begin(),coll.end(),val),coll.end);
std::vectorcoll;
auto pos=find(coll.begin(),coll.end(),val);
if(pos!=coll.end())coll.erase(pos);
注:上面的一种为删除所指定的所有元素,下面这一种为删除指定的第一个元素
基于vector内置实现是一个dynamic array,所以在你需要一个动态数组的时候便可以使用vector。例如你可以利用vector存放常用的C字符串(类型为char*或const char*)
std::vectorv;
v.resize(41);
strcpy(&v[0],"hello world");
printf("%s\n",&v[0]);
注:自C++11起,如果你想直接访问vector的元素,不一定要用&a[0],因为成员函数data()也具备同样功能
std::vectorv;
strcpy(v.data(),"hello world");
printf("%s/n",v.data());
基于C-style Array的特性,在将vector作为其实现时,一定要确保vector大小足够容纳复制进来的数据,例如当作C-string看时,必须会放置一个'\0'元素在vector末端。
注:虽然随机访问迭代器很像pointer,但vector迭代器是由具体实现定义的,也许并不是一个寻常pointer.
printf("%s\n",v.begin()); //ERROR
printf("%s\n",v.data()); //OK
printf("%s\n",&v[0]); //OK
Vector只支持最低限度的逻辑错误检查。Subscript(下标)操作符的安全版本at()是唯一被C++standard认可得以抛出异常的函数
如果vector调用的函数抛出异常C++标准库做出以下保证:
如果push_back()安插元素时抛出异常,函数将不产生效用
如果元素的copy/move操作不抛出异常,那么inert(),emplace(),emplace_back(),erase()和push_back()要么成功,要么就不产生效用
pop_back()绝对不会抛出任何的异常
swap()和clear()不抛出异常
注:所有这些保证都基于一个条件:析构函数不得抛出异常
下面一个例子展现vector的一个基本用法
#include
#include
#include
#include
#include
using namespace std;
int main(){
vectorsentence;
sentence.reserve(5);
sentence.push_back("Hello,");
sentence.insert(sentence.end(),{"how","are","you","?"});
copy(sentence.cbegin(),sentence.cend(),ostream_iterator(cout," "));
cout<(cout," "));
cout<
输出可能结果如下:
Hello, how are you?
max_size():1073741823
size():5
capacity():5
Hello, you are how always !
size():6
capacity():6
size():4
capacity():4
参考书籍 《C++标准库》(第二版)