C++STL剖析(二)—— vector的概念和使用

文章目录

  • 1. vector的介绍
  • 2. vector的常见构造
  • 3. vector的遍历方式
    • [ ] + 下标
    • 迭代器
    • 范围for
  • 4. vector 迭代器使用
    • begin 和 end
    • rbegin 和 rend
  • 5. vector 空间增长问题
    • size
    • capacity
    • reserve
    • resize
    • empty
  • 6. vector 的增删查改
    • push_back
    • pop_back
    • insert
    • erase
    • find
    • swap
    • operator[ ]
    • sort
  • 7. vector 迭代器失效问题
    • 失效场景
    • 解决办法
  • 8. 总结


1. vector的介绍

  • vector 是表示可变大小数组的序列容器。

  • vector 就像数组一样,采用连续的存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

  • vector 使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector 并不会每次都重新分配大小。

  • vector 分配空间策略:vector 会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

  • vector 占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

  • 与其它动态序列容器相比(deques、lists and forward_lists), vector 在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起 lists 和 forward_lists 统一的迭代器和引用更好。

我们学习 vector 也和学习 string 一样,参考官方的文档:vector的文档介绍

2. vector的常见构造

这里主要有 4 中构造方式:

C++STL剖析(二)—— vector的概念和使用_第1张图片

(1)无参构造一个空容器

vector<int> v1; //构造一个int类型的空容器

(2)构造并初始化 n 个 val 的容器

vector<int> v2(10, 5); //构造含有10个5的int类型容器

(3)拷贝构造某类型容器

vector<int> v3(v2); //拷贝构造int类型的v2容器

(4)使用迭代器进行初始化构造

vector<int> v4(v2.begin(), v2.end()); //使用迭代器拷贝构造v2容器的某一段内容

注意,vector 不只是能够用来构造 int 类型容器,还可以使用迭代器构造其他类型的容器

string s("hello world");

vector<char> v5(s.begin(), s.end()); //拷贝构造string对象的某一段内容

3. vector的遍历方式

vector 的遍历和 string 一样,也分为三种。

[ ] + 下标

vector 对 [ ] 运算符进行了重载,所以我们可以直接使用 [ ]+下标 访问对象中的元素。

还可以通过 [ ]+下标 修改对应位置的元素。

代码示例

int main()
{
	vector<int> v; // 定义容器v1

	// 尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	// 使用下标访问数据
	for (size_t i = 0; i < v.size(); ++i)
	{
		cout << v[i] << " ";
	}
	cout << endl;

	// 使用下标修改数据
	for (size_t i = 0; i < v.size(); ++i)
	{
		v[i] += 1;
		cout << v[i] << " ";
	}
	cout << endl;

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第2张图片

迭代器

begin 获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器

代码示例

int main()
{
	vector<int> v; // 定义容器v1

	// 尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	// 使用迭代器访问数据
	vector<int>::iterator it1 = v.begin();
	while (it1 != v.end())
	{
		cout << *it1 << " ";
		it1++;
	}
	cout << endl;

	// 使用迭代器修改数据
	vector<int>::iterator it2 = v.begin();
	while (it2 != v.end())
	{
		*it2 += 1;
		cout << *it2 << " ";
		it2++;
	}
	
	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第3张图片

范围for

和 string 一样,如果我们是通过范围 for 来修改对象的元素,那么接收元素的变量 e 的类型必须是引用类型,否则 e 只是对象元素的拷贝,对 e 的修改不会影响到对象的元素。

代码示例

int main()
{
	vector<int> v; // 定义容器v1

	// 尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	// 使用范围for访问数据
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	// 使用范围for修改数据
	for (auto& e : v)
	{
		e += 1;
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第4张图片

4. vector 迭代器使用

vector 的迭代器和 string 一样,也分为 正向迭代器 和 反向迭代器。

正向迭代器和 const正向迭代器:

C++STL剖析(二)—— vector的概念和使用_第5张图片

反向迭代器 和 const 反向迭代器

C++STL剖析(二)—— vector的概念和使用_第6张图片

它们的原理如下图所示(和 string 一样):

C++STL剖析(二)—— vector的概念和使用_第7张图片

begin 和 end

通过 begin 函数可以得到容器中第一个元素的正向迭代器,通过 end 函数可以得到容器中最后一个元素的后一个位置的正向迭代器。

正向迭代器遍历容器:

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back插入5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//正向迭代器遍历容器
	vector<int>::iterator it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		it++;
	}

	return 0;
}

调试运行

C++STL剖析(二)—— vector的概念和使用_第8张图片

rbegin 和 rend

通过 rbegin 函数可以得到容器中最后一个元素的反向迭代器,通过 rend 函数可以得到容器中第一个元素的前一个位置的反向迭代器。

反向迭代器遍历容器:

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back插入5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//反向迭代器遍历容器
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend()) {
		cout << *rit << " ";
		rit++;
	}

	return 0;
}

调试运行

C++STL剖析(二)—— vector的概念和使用_第9张图片

注意:const 正向和反向这里就不演示了,和 string 的原理一样

5. vector 空间增长问题

主要学习以下几个函数

C++STL剖析(二)—— vector的概念和使用_第10张图片

size

size 函数获取当前容器中的有效元素个数。

C++STL剖析(二)—— vector的概念和使用_第11张图片

代码示例

int main()
{
	//定义容器v并初始化为20个5
	vector<int> v(20, 5);

	cout << v.size() << endl; //获取当前容器中的有效元素个数

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第12张图片

capacity

capacity 函数获取当前容器的最大容量。

C++STL剖析(二)—— vector的概念和使用_第13张图片

代码示例

int main()
{
	//定义容器v并初始化为30个5
	vector<int> v(30, 5);

	cout << v.capacity() << endl; //获取当前容器的最大容量

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第14张图片

这里我们思考一个问题:capacity 是如何增容的呢?

可以用下面代码来验证一下

int main()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making foo grow:\n";
	for (int i = 0; i < 100; ++i) {
		v.push_back(i);
		if (sz != v.capacity()) {
			sz = v.capacity();
			cout << "capacity changed: " << sz << endl;
		}
	}
	
	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第15张图片

可以看到,在 VS2019 下,capacity 是按照大概 1.5 倍增长的。

那么 Linux 下呢?这里我也测试了一下,如图,大概是按照 2 倍增长的。

C++STL剖析(二)—— vector的概念和使用_第16张图片

为什么 VS 和 Linux 下,capacity 增长的方式是不一样的呢?

很简单,因为早期的 STL 其实就是一个规范:

  • VS 下用的是 PJ 版本,大概是按 1.5 倍进行增容的。
  • Linux g++ 下是 SGI 版本,大概是按 2 倍进行增容的。

我们之前学数据结构知道,顺序表增容都是 2 倍的,所以不要固化的认为 vector 也是一样,具体增长多少是根据具体的需求定义的。

reserve

reserse 函数改变容器的最大容量。

(1)当所给值大于容器当前的 capacity 时,将 capacity 扩大到该值。

(2)当所给值小于容器当前的 capacity 时,什么也不做。

C++STL剖析(二)—— vector的概念和使用_第17张图片

假设我事先知道要插入 100 个字符,那么我们可以使用 reserve 提前开好空间

int main()
{

	size_t sz;
	vector<int> v;
	v.reserve(100); // 提前开好100空间
	sz = v.capacity();
	cout << "making foo grow:\n";
	for (int i = 0; i < 100; ++i) {
		v.push_back(i);
		if (sz != v.capacity()) {
			sz = v.capacity();
			cout << "capacity changed: " << sz << endl;
		}
	}

	return 0;
}

可以看到,当我们提前开好空间以后,容器并没有自己再去开辟空间

C++STL剖析(二)—— vector的概念和使用_第18张图片

resize

resize 函数改变容器中的有效元素个数。

(1)当所给值大于容器当前的 size 时,将 size 扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为 0。

(2)当所给值小于容器当前的 size 时,将 size 缩小到该值。

C++STL剖析(二)—— vector的概念和使用_第19张图片

代码示例

int main()
{

	size_t sz;
	vector<int> v;
	v.resize(100); // 开好100空间并全部初始化
	sz = v.capacity();
	cout << "making foo grow:\n";
	for (int i = 0; i < 100; ++i) {
		v.push_back(i);
		if (sz != v.capacity()) {
			sz = v.capacity();
			cout << "capacity changed: " << sz << endl;
		}
	}

	return 0;
}

可以看到,当我们使用 resize 的时候,除了进行开空间,还对容器进行了初始化

C++STL剖析(二)—— vector的概念和使用_第20张图片

reserve 和 resize 综合演示

代码示例

int main()
{

	//初始化容器
	vector<int> v(10, 5);

	//打印size和capacity
	cout << v.size() << endl; //10
	cout << v.capacity() << endl; //10

	cout << endl;

	//改变容器的capacity为20,size不变
	v.reserve(20);
	cout << v.size() << endl; //10
	cout << v.capacity() << endl; //20

	cout << endl;

	//改变容器的size为15,capacity不变
	v.resize(15);
	cout << v.size() << endl; //15
	cout << v.capacity() << endl; //20

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第21张图片

注意:

  • reserve 只负责开辟空间,如果确定知道需要用多少空间,reserve 可以缓解 vector 增容的代价缺陷问题。

  • resize 在开空间的同时还会进行初始化,影响 size。

empty

empty 函数判断当前容器是否为空。

(1)如果容器为空,那么就输出 1

(2)如果容器不为空,那么就输出 0

C++STL剖析(二)—— vector的概念和使用_第22张图片

代码示例

int main()
{
	vector<int> v1(10, 5);
	cout << v1.empty() << endl;

	vector<int> v2;
	cout << v2.empty() << endl; 

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第23张图片

6. vector 的增删查改

对于 vector 的增删查改主要是以下几个函数
C++STL剖析(二)—— vector的概念和使用_第24张图片

push_back

push_back 函数对容器进行尾插。

C++STL剖析(二)—— vector的概念和使用_第25张图片

代码示例

int main()
{

	//定义容器v
	vector<int> v;

	//使用push_back插入5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第26张图片

pop_back

pop_back 函数对容器进行尾删

在这里插入图片描述

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//使用pop_back尾删4个数据
	v.pop_back();
	v.pop_back();
	v.pop_back();
	v.pop_back();

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第27张图片

insert

insert 函数可以在所给迭代器位置插入一个或多个元素

C++STL剖析(二)—— vector的概念和使用_第28张图片

(1)在 pos 位置插入一个值

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//在容器头部插入0
	v.insert(v.begin(), 10);

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第29张图片

(2)在 pos 位置插入 n 个值

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//在容器头部插入5个10
	v.insert(v.begin(), 5, 10);

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第30张图片

erase

erase 函数可以删除所给迭代器位置的元素,或删除所给迭代器区间内的所有元素(左闭右开)

C++STL剖析(二)—— vector的概念和使用_第31张图片

(1)删除一个值

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插5个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//头删
	v.erase(v.begin());

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第32张图片

(2)删除一段区间

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插8个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);
	v.push_back(7);
	v.push_back(8);

	//删除在该迭代器区间内的元素(左闭右开]
	v.erase(v.begin(), v.begin() + 3);

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第33张图片

注意:以上都是按照特定的位置进行插入或删除元素的方式,若要按值进行插入或删除(在某一特定值位置进行插入或删除),则需要用到 find 函数。

find

vector 没有 find 函数,那么假设我要查找某个元素怎么办呢?

很简单,可以去调用算法库里面的一个函数接口:find

在这里插入图片描述

find 函数共三个参数,前两个参数确定一个迭代器区间(左闭右开),第三个参数确定所要寻找的值。

函数在所给迭代器区间寻找第一个匹配的元素,并返回它的迭代器,若未找到,则返回所给的第二个参数。

代码示例

int main()
{
	//定义容器v
	vector<int> v;

	//使用push_back尾插6个数据
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	// 假设我要3的前面插入300
	//vector::iterator pos = find(v.begin(), v.end(), 3);
	auto pos = find(v.begin(), v.end(), 3);
	if (pos != v.end())
	{
		cout << "找到了" << endl;
		v.insert(pos, 300);
	}
	else
	{
		cout << "没有找到" << endl;
	}

	//打印
	for (auto e : v) {
		cout << e << " ";
	}

	return 0;
}

调试运行

C++STL剖析(二)—— vector的概念和使用_第34张图片

注意:因为 find 函数是在算法库里面的,所以需要加头文件 #include

swap

通过 swap 函数可以交换两个容器的数据空间,实现两个容器的交换。

在这里插入图片描述

代码示例

int main()
{
	//定义v1容器
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(1);
	v1.push_back(1);

	//定义v2容器
	vector<int> v2;
	v2.push_back(2);
	v2.push_back(2);
	v2.push_back(2);

	//交换v1和v2的数据
	v1.swap(v2);

	//打印v1
	for (auto e1 : v1) {
		cout << e1 << " ";
	}

	//打印v2
	for (auto e2 : v2) {
		cout << e2 << " ";
	}
	
	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第35张图片

operator[ ]

vector 中实现了 [ ] 操作符的重载,因此我们也可以通过 下标 + [ ] 的方式对容器当中的元素进行访问。

在这里插入图片描述

代码示例

int main()
{
	//定义v1容器
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	// 通过[]读写第0个位置。
	cout << v[0] << endl;

	// 通过[i]的方式遍历vector
	for (size_t i = 0; i < v.size(); ++i) {
		cout << v[i] << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第36张图片

sort

sort 是算法库里面一个函数接口,它默认是排升序的,要传一段 左闭右开 的区间。

C++STL剖析(二)—— vector的概念和使用_第37张图片

代码示例

int main()
{
	//定义v1容器
	vector<int> v;
	v.push_back(9);
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(0);
	v.push_back(-1);

	// 默认排升序
	sort(v.begin(), v.end());

	// 打印
	for (auto e : v)
	{
		cout << e << " ";
	}
	
	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第38张图片

如果想要排降序的话,需要使用仿函数,而且要带头文件 #include

代码示例

int main()
{
	//定义v1容器
	vector<int> v;
	v.push_back(9);
	v.push_back(1);
	v.push_back(5);
	v.push_back(2);
	v.push_back(0);
	v.push_back(-1);

	// 默认排升序
	sort(v.begin(), v.end(), greater<int>());

	// 打印
	for (auto e : v)
	{
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第39张图片

7. vector 迭代器失效问题

我们上面学习了 insert 和 erase 函数,那么思考一个问题,为什么 insert 和 erase 的返回值是 iterator 迭代器呢?

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector 的迭代器就是原生态指针 T*

因此,迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

失效场景

(1)场景一

在下面代码中,我们在数组中 2 的位置插入一个 10,然后将 2 删除。

我们使用 find 获取的是指向 2 的指针以后,当我们在 2 的位置插入 10 后,该指针就指向了 10,所以我们之后删除的实际上是 10,而不是 2。

代码示例

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	auto pos = find(v.begin(), v.end(), 3); //获取值为3的元素的迭代器

	// 1 2 30 3 4 5
	v.insert(pos, 10); // 在3的位置前插入30

	// 1 2 3 4 5
	v.erase(pos); // 删除pos位置的数据,导致pos迭代器失效。

	//此处我们再访问pos位置的值,会导致非法访问
	cout << *pos << endl;

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第40张图片

erase 删除 pos 位置元素后,pos 位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效。

但是,如果 pos 刚好是最后一个元素,删完之后 pos 刚好是 end 的位置,而 end 位置是没有元素的,那么 pos 就失效了。

因此删除 vector 中任意位置上元素时,vs 就认为该位置迭代器失效了。

(1)场景二

把 vector 数组中的偶数全部删除。

代码示例

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	auto it = v.begin();

	while (it != v.end())
	{
		if (*it % 2 == 0) //删除容器当中的全部偶数
		{
			v.erase(it);
		}
		it++;
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第41张图片

为什么运行起来会报错呢?因为迭代器访问到了不属于容器的内存空间,导致程序崩溃。

C++STL剖析(二)—— vector的概念和使用_第42张图片

不仅如此,而且在迭代器遍历容器中的元素进行判断时,并没有对 1、3、5 元素进行判断。

以上操作,都有可能会导致 vector 扩容,也就是说 vector 底层原理旧空间被释放掉,而在打印时,it 还使用的是释放之间的旧空间,在对 it 迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。

解决办法

vector 迭代器失效有 2 种:

  • 扩容、缩容,导致野指针失效
  • 迭代器指向的位置意义变了

所以我们要重新接收,重新处理,也就是说每次使用前,对迭代器进行重新赋值。

(1)场景一解决方案

对于实例一,我们在使用迭代器删除元素 2 时对其进行重新赋值便可以解决。

代码示例

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);

	//获取值为2的元素的迭代器
	auto pos = find(v.begin(), v.end(), 2);

	//在值为2的元素的位置插入10
	v.insert(pos, 10);

	//重新获取值为2的元素的迭代器
	pos = find(v.begin(), v.end(), 2);

	//删除元素2
	v.erase(pos);

	// 打印
	for (auto e : v)
	{
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第43张图片

(2)场景二解决方案

对于实例二,我们可以接收 erase 函数的返回值(erase 函数返回删除元素的后一个元素的新位置)。

并且控制代码的逻辑是:当元素被删除后继续判断该位置的元素(因为该位置的元素已经更新,需要再次判断)。

代码示例

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	auto it = v.begin();

	while (it != v.end())
	{
		if (*it % 2 == 0) // 删除容器当中的全部偶数
		{
			it = v.erase(it); // 删除后获取下一个元素的迭代器
		}
		else
		{
			it++; // 是奇数则it++
		}
	}

	// 打印
	for (auto e : v)
	{
		cout << e << " ";
	}

	return 0;
}

运行结果

C++STL剖析(二)—— vector的概念和使用_第44张图片

8. 总结

通过上面的练习我们发现 vector 常用的接口更多是插入和遍历。

遍历更喜欢用数组 operator[i] 的形式访问,因为这样便捷。

大家可以多去刷一些 OJ 题以此来增强学习 vector 的使用。

你可能感兴趣的:(c++,面向对象,STL)