C++ vector容器的使用(非常详细)
vector 容器与动态数组相同,在插入或删除元素时能够自动调整自身大小,即 vector 容器能够自动处理存储数据所需的空间。
vector 容器中的元素放置在连续的内存空间中,可以使用迭代器对其进行访问和遍历。vector 容器的存储结构如图1所示。

图1 vector容器的存储结构
vector 容器在插入元素时,插入位置之后的元素都要被顺序地向后移动,因此,在总体上 vector 容器插入操作效率并不高。插入位置越靠前,执行插入所需的时间就越多,但在 vector 容器尾部插入元素的效率比较高。
删除 vector 容器中的元素时,被删除元素后面的元素会顺序向前移动,将被删除元素留下的空位补上。删除操作的效率和插入类似,被删除元素越靠前,删除操作所需的时间就越多。
下面讲解 vector 容器的常见用法。
需要注意的是,vector 对象在定义后所有元素都会被初始化,如果是基本数据类型的容器,则都会被初始化为 0;如果是其他类型容器,则由类的默认构造函数初始化。
vector 提供了两个函数 capacity() 和 size(),分别用于获取容器容量和容器实际元素个数,这两个函数的调用形式如下所示:
at() 函数调用形式如下所示:
assign() 函数有两种重载形式,分别如下所示:
注意,区间是
front() 函数和 back() 函数调用形式如下所示:
push_back() 函数和 pop_back() 函数调用形式如下所示:
【示例1】下面通过案例演示 vector 容器的用法,C++ 代码入下:
vector容器提供了 iterator、const_iterator、reverse_iterator 和 const_reverse_iterator 四种迭代器,这四种迭代器作用分别如下:
在使用迭代器之前,必须先定义迭代器对象,vector 容器迭代器对象的定义格式如下所示:
vector 提供了获取上述四种迭代器的成员函数,如表 1 所示。
注意,迭代器遍历容器到达尾部时,指向最后一个元素的后面,而不是指向最后一个元素,即使用 end() 函数、rend() 函数、cend() 函数和 crend() 函数获取的迭代器,指向最后一个元素后面的位置,而不是指向最后一个元素。
【示例2】下面通过案例演示迭代器的用法,C++ 代码如下:
其中,insert() 函数用于向容器中插入元素,它有三种重载形式,分别如下所示:
【示例3】下面通过案例演示这两个函数的用法,C++ 代码如下:
注意,删除区间元素时,区间是左闭右开,即第2个位置上的元素会删除,而第6个位置上的元素不会删除。由图7-6可知,erase()函数删除了5个元素t。
deque 容器的存储结构如图 2 所示。

图2 deque容器的存储结构
deque 的操作方法和 vector 容器几乎相同。最大的区别是 deque 容器不支持 vector 容器中的 reserve()函数、capacity() 函数和 data() 函数,并且新增了 pop_front()、push_front() 函数,用于从队首弹出、插入元素。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
vector 容器中的元素放置在连续的内存空间中,可以使用迭代器对其进行访问和遍历。vector 容器的存储结构如图1所示。

图1 vector容器的存储结构
vector 容器在插入元素时,插入位置之后的元素都要被顺序地向后移动,因此,在总体上 vector 容器插入操作效率并不高。插入位置越靠前,执行插入所需的时间就越多,但在 vector 容器尾部插入元素的效率比较高。
删除 vector 容器中的元素时,被删除元素后面的元素会顺序向前移动,将被删除元素留下的空位补上。删除操作的效率和插入类似,被删除元素越靠前,删除操作所需的时间就越多。
下面讲解 vector 容器的常见用法。
创建vector容器
vector 模板中定义了多个重载构造函数,因此vector容器的创建与初始化也有多种方式。vector 容器的创建方式主要有四种。1) 指定容器大小
指定容器大小的格式如下:vector<元素类型> 对象名(容器大小);
在上述格式中,“<>”中的元素类型名表示容器中元素的类型,如 int 表示容器中存储的是 int 类型的数据。“()”中指定容器大小。示例代码如下所示:vector<int> v1(10); vector<string> v2(5);上述代码说明:
- 第一行代码创建了一个存储 int 类型数据的容器 v1,容器大小为 10;
- 第二行代码创建了一个存储 string 类型数据的容器 v2,容器大小为 5。
需要注意的是,vector 对象在定义后所有元素都会被初始化,如果是基本数据类型的容器,则都会被初始化为 0;如果是其他类型容器,则由类的默认构造函数初始化。
2) 指定初始值
在创建 vector 容器时,可以同时指定 vector 容器大小和初始值,格式如下所示:vector<元素类型>对象名(容器大小,元素初始值);
按照上述格式创建 vector 容器,示例代码如下所示:vector<int> v1(10, 1); vector<string> v3(3, "aa");上述代码说明:
- 第一行代码创建存储 int 类型数据的容器 v1,容器大小为 10,10 个元素的初始值均为 1。
- 第二行代码创建存储 string 类型数据的容器 v2,容器大小为 3,3 个元素的初始值均为 "aa"。
3) 列表初始化
C++11 新标准还提供了另外一种 vector 容器初始化方式,即用值的列表初始化,示例代码如下所示:vector<int> v1{1, 2}; //v1有两个元素 vector<string> v2 = { "a", "b", "c" }; //v2有三个元素使用列表初始化时,带“=”符号与不带“=”符号均可。
4) 初始化状态为空
初始化状态为空,即创建 vector 对象时不指定大小也不指定初始值,示例代码如下所示:vector<int> v1; //创建存储int类型数据的容器v1除了上述方式,vector 容器还可以用另外一个 vector 容器完成初始化,示例代码如下所示:
vector<int> v1(10, 1); vector<int> v2(v1); //用容器v1初始化容器v2 vector<int> v3 = v2; //用容器v2给容器v3赋值需要注意的是,用一个 vector 容器初始化另一个容器或相互赋值时,两个 vector 容器的元素类型必须相同。
获取容器容量和实际元素个数
vector 容器的容量与容器实际元素个数并不一定相同,容器容量指容器最多可以存储的元素个数,是容器预分配的内存空间。而容器实际元素个数可能小于容器容量。vector 提供了两个函数 capacity() 和 size(),分别用于获取容器容量和容器实际元素个数,这两个函数的调用形式如下所示:
v.capacity(); v.size();上述代码说明:
- v 是创建的 vector 容器,如无特殊说明,后续讲解的 vector 容器的函数调用,其中 v 均指 vector 容器。
- capacity() 函数返回容器的容量,size() 函数返回容器实际元素个数。
访问容器中的元素
由于 vector 重载了[]
运算符,因此可以使用索引方式访问 vector 容器中的元素。此外,vector 容器还提供了一个成员函数 at(),用于随机访问容器中的元素。at() 函数调用形式如下所示:
v.at(int idx);在上述 at() 函数的调用形式中,参数 idx 表示索引。at() 函数返回值为索引指向的数据。
赋值函数
vector 容器中的元素可以在创建容器时指定,也可以通过[]
运算符完成赋值。除此之外,vector 容器还提供了一个成员函数 assign(),用于给空的 vector 容器赋值。assign() 函数有两种重载形式,分别如下所示:
v.assign(n, elem); //将n个elem元素赋值给容器 v.assign(begin, end); //将[begin, end)区间中的元素赋值给容器assign() 函数的两种重载形式都可以完成容器元素赋值:
- 第一种形式给元素赋同样的数据值;
- 第二种形式以指定区间给元素赋值。
注意,区间是
左闭右开
,即第一个区间值可以使用,最后一个区间值不可以使用。
获取头部和尾部元素
vector 容器提供了 front() 函数与 back() 函数,分别用于获取容器的头、尾元素。front() 函数和 back() 函数调用形式如下所示:
v.front(); //获取容器头部元素(第一个元素) v.back(); //获取容器尾部元素(最后一个元素) v.front(); //获取容器头部元素(第一个元素) v.back(); //获取容器尾部元素(最后一个元素)
从尾部插入和删除元素
vector 容器提供了一对函数 push_back() 与 pop_back(),分别用于从尾部添加元素和删除尾部元素。push_back() 函数和 pop_back() 函数调用形式如下所示:
v.push_back(type elem& t); v.pop_back();
【示例1】下面通过案例演示 vector 容器的用法,C++ 代码入下:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> v; //创建一个空的vector容器v for(int i=0;i<10;i++) v.push_back(i+1); //从尾部向容器v中插入10个元素 for(int i=0;i<10;i++) cout<<v[i]<<" "; //输出容器v中的元素 cout<<endl; v.pop_back(); //删除尾部元素 for(int i=0;i<9;i++) //此时元素个数为9 cout<<v[i]<<" "; //输出容器v中的元素 cout<<endl; return 0; }运行结果:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9
- 第 6 行代码创建了一个空的 vector 容器 v;
- 第 7~10 行代码在 for 循环中调用 push_back() 函数向容器尾部添加元素,并输出容器 v 中元素;
- 第 12 行代码调用 pop_back() 函数删除了末尾的元素 10;
- 第 13~14 行代码在 for 循环中输出容器v中的元素。
容器的迭代器
vector 容器提供了迭代器,通过迭代器可以访问、修改容器中的元素。vector容器提供了 iterator、const_iterator、reverse_iterator 和 const_reverse_iterator 四种迭代器,这四种迭代器作用分别如下:
- iterator:正向遍历容器元素。
- reverse_iterator:反向遍历容器元素。
- const_iterator:正向遍历容器元素,但通过 const_iterator 只能访问容器元素,不能修改元素的值。
- const_reverse_iterator:反向遍历容器元素,但通过 const_reverse_iterator 只能访问容器元素,不能修改元素的值。
在使用迭代器之前,必须先定义迭代器对象,vector 容器迭代器对象的定义格式如下所示:
vector<元素类型> 迭代器 迭代器对象名称;
在实际编程中,通常将创建的迭代器对象简称为迭代器。迭代器可以执行++
、−−
、与整数相加减等算术运算,以达到遍历容器元素的目的。vector 提供了获取上述四种迭代器的成员函数,如表 1 所示。
函数 | 含义 |
---|---|
begin() | 返回容器的起始位置的迭代器 iterator |
end() | 返回迭代器的结束位置的迭代器 iterator |
rbegin() | 返回容器结束位置作为起始位置的反向迭代器 reverse_iterator |
rend() | 返回反向迭代的最后一个元素之后的位置的反向迭代器 reverse_iterator |
cbegin() | 返回容器中起始位置的常量迭代器 const_iterator,不能修改迭代器指向的内容(C++11) |
cend() | 返回迭代器的结束位置的常量迭代器 const_iterator,不能修改迭代器指向的内容(C++11) |
crbegin() | 返回容器结束位置作为起始位置的迭代器 const_reverse_iterator(C++11) |
crend() | 返回第一个元素之前位置的常量迭代器 const_iterator (C++11) |
注意,迭代器遍历容器到达尾部时,指向最后一个元素的后面,而不是指向最后一个元素,即使用 end() 函数、rend() 函数、cend() 函数和 crend() 函数获取的迭代器,指向最后一个元素后面的位置,而不是指向最后一个元素。
【示例2】下面通过案例演示迭代器的用法,C++ 代码如下:
#include<iostream> #include<vector> using namespace std; int main() { vector<int> c={1,2,3}; //创建vector容器c vector<int>::iterator pos; //定义iterator迭代器pos vector<int>::reverse_iterator pos_r; //定义reverse_iterator迭代器pos_r cout<<"iterator迭代器:"; for(pos=c.begin();pos!=c.end();++pos) //使用迭代器pos遍历容器c中的元素 { cout<<*pos<<" "; } cout<<endl<<"reverse_iterator迭代器:"; //使用迭代器pos_r反向遍历容器c中的元素 for(pos_r=c.rbegin();pos_r!=c.rend();++pos_r) { cout<<*pos_r<<" "; } return 0; }运行结果:
iterator迭代器:1 2 3
reverse_iterator迭代器:3 2 1
- 第 6 行代码创建了一个 vector 容器 c;
- 第 7~8 行代码分别创建了 iterator 迭代器对象 pos 和 reverse_iterator 代器对象 pos_r;
- 第 10~13 行代码通过 for 循环使用迭代器 pos 遍历容器 c 中的元素并输出;
- 第 16~19 行代码通过 for 循环使用迭代器 pos_r 遍历容器 c。
小提示:迭代器失效:vector 容器是一个顺序容器,在内存中是一块连续的内存,当插入或删除一个元素后,内存中的数据会移动,从而保证数据的连续。当插入或删除数据后,其他数据的地址可能会发生变化,迭代器获取容器位置信息的数据不正确,即迭代器失效,会导致访问出错。
在任意位置插入和删除元素
vector 提供了一对向容器任意位置插入和删除元素的函数 insert() 与 erase()。其中,insert() 函数用于向容器中插入元素,它有三种重载形式,分别如下所示:
v.insert(pos, elem); //在pos位置插入元素elem v.insert(pos, n, elem): //在pos位置插入n个elem元素 v.insert(pos, begin, end); //在pos位置插入[begin, end)区间的数据erase() 函数用于删除容器中的元素,它有两种重载形式,分别如下所示:
v.erase(pos); //删除pos位置上的元素 v.erase(begin, end); //删除[begin, end)区间的数据insert() 函数与 erase() 函数中的位置参数只能由 begin()、end() 等函数返回的迭代器指示,不能用纯粹的数字。
【示例3】下面通过案例演示这两个函数的用法,C++ 代码如下:
#include<iostream> #include<vector> using namespace std; int main() { vector<char> v; //创建空的vector容器v v.insert(v.begin(), 'a'); //在头部位置插入元素a v.insert(v.begin(), 'b'); //在头部位置插入元素b v.insert(v.begin(), 'c'); //在头部位置插入元素c v.insert(v.begin() + 1, 5, 't'); //在v.begin()+1位置插入5个元素t for(int i = 0; i < 8; i++) //输出容器v中的元素 cout << v[i] << " "; cout << endl; cout << "after erase elems:\n"; //删除begin()+1到begin()+6区间的5个元素 v.erase(v.begin() + 1, v.begin() + 6); for(int i = 0; i <3; i++) //输出容器v中的元素 cout << v[i] << " "; cout << endl; return 0; }运行结果:
c t t t t t b a
after erase elems:
c b a
- 第 6 行代码创建了一个存储char类型数据的空容器 v;
- 第 7~9行 代码调用 insert() 函数在容器 v 头部分别插入元素 a、b、c;
- 第 10 行代码调用 insert() 函数在容器第 2 个位置插入 5 个元素 t,此时,元素 b 和元素 a 会依次向后移动 5 个位置;
- 第 11~12 行代码通过 for 循环遍历输出容器v中的元素;
- 第 16 行代码调用 erase() 函数删除第 2 个位置到第 6 个位置之间的 5 个元素。
注意,删除区间元素时,区间是左闭右开,即第2个位置上的元素会删除,而第6个位置上的元素不会删除。由图7-6可知,erase()函数删除了5个元素t。
多学一招:deque容器
deque 容器与 vector 容器非常相似,采用动态内存管理的方式存储元素。与 vector 不同的是,deque 是两端开口的,支持从两端插入、删除数据,并支持元素的随机访问。deque 容器的存储结构如图 2 所示。

图2 deque容器的存储结构
deque 的操作方法和 vector 容器几乎相同。最大的区别是 deque 容器不支持 vector 容器中的 reserve()函数、capacity() 函数和 data() 函数,并且新增了 pop_front()、push_front() 函数,用于从队首弹出、插入元素。
声明:《C++系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。