【STL】vector的使用

这篇具有很好参考价值的文章主要介绍了【STL】vector的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

默认成员函数

构造函数

拷贝构造

赋值重载

迭代器

正向迭代器

反向迭代器

容量管理

查看容量和大小

扩容

判空

访问数据

下标访问

边界访问

数据修改

尾插尾删

指定位置插入删除

迭代器失效 

清空

​编辑

交换

查找数据

vector可以代替string吗


前言

讲完string和string的模拟实现,今天讲讲vector的使用。虽然说它叫vector,使用时还是我们平常使用的数组,只不过会自动地调节分配的空间。由于在空间中使用的一块连续的空间,因此支持下标访问,使用起来相当地便利,与我们之前学习的string的区别就在于,string只能存储字符,而vector可以存储任意类型的数据。


默认成员函数

构造函数

在 C++98 中有三种构造函数可以对 vector 进行初始化,分别是:

  • 无参进行构造
  • 放入n个相同数据
  • 根据迭代器区间进行构造

其中的 allocator 是空间配置器,只是用于分配空间,目的为增加申请释放空间的效率。

【STL】vector的使用

因为 vector 是一个模板类,因此实例化的时候要声明内置类型。例如 vector 中要存 int 类型的数据便写作 vector<int> ,这样才是其完整的类型名。现在我们就可以试试以不同的构造函数来初始化 vector 了。

[注意]: 使用vector时要包含头文件<vector>!!

int main()
{
	string s("abcd");
	vector<int> v1;
	vector<int> v2(3, 2);
	vector<int> v3(s.begin(), s.end());

	return 0;
}

 【STL】vector的使用【STL】vector的使用【STL】vector的使用

v3 中之所以是 97 98 99 100 是因为模板参数选择的是 int 因此 v3 中存的是字符的 ASCII 码。

也可以这样子定义,本质上是发生了一次拷贝构造,这样使用更加与数据接近更加形象和简便。

int main()
{
	vector<int> v4 = { 1,2,3,4,5 };
	return 0;
}

 【STL】vector的使用

拷贝构造

vector 的拷贝构造便是支持对同类型 vector 的拷贝。

【STL】vector的使用

int main()
{
	vector<int> v1({ 1,2,3,4,5 });
	vector<int> v2 = v1;
	return 0;
}

 【STL】vector的使用【STL】vector的使用

 若是模板参数不同的 vector 便无法进行拷贝构造

 【STL】vector的使用【STL】vector的使用

赋值重载

【STL】vector的使用

赋值重载用于对已存在的两个 vector 之间进行赋值,就是值之间的拷贝。

【STL】vector的使用         【STL】vector的使用

迭代器

迭代器作为 STL 六大组件,必然是绕不开的话题。库中也准备了多种的迭代器供使用者选择。

【STL】vector的使用

正向迭代器

正向迭代器由 begin 开始 end 结束,直接使用起来与 string 的迭代器并无区别。

【STL】vector的使用

【STL】vector的使用

借助迭代器我们既可以直接使用迭代器,也可以使用范围 for 完成对 vector 的遍历了。

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };
	vector<int>::iterator it = v1.begin();
    //auto it = v1.begin();     也可以直接使用auto
	while (it != v1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	for (auto it : v1)
	{
		cout << it << " ";
	}
	cout << endl;
	return 0;
}

【STL】vector的使用  

反向迭代器

反向的迭代器名称为 reverse_iterator,其接口为 rbegin 和 rend ,使用起来与正向迭代器类似。

但值得注意的一点是:范围 for 只能进行正向的遍历,无法反向

【STL】vector的使用 【STL】vector的使用

int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,9 };
	vector<int>::reverse_iterator it = v1.rbegin();
	//auto it = v1.rbegin();
	while (it != v1.rend())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	return 0;
}

 【STL】vector的使用

容量管理

查看容量和大小

跟 string 一样,我们可以通过 size 和 capacity 两个接口分别访问 vector 的和容量,通过这两个接口也有效帮助我们确定访问时的边界值。

【STL】vector的使用

【STL】vector的使用

扩容

【STL】vector的使用

 通过 reserve 我们能够对 capacity 进行修改,根据传入值的大小会有两种处理方式。

  • n 大于 capacity 时会重新分配一块更大的空间给 vector ,将 capacity 增长到 n 或更大。
  • 其他情况下便不进行处理

同时,reserve 不会更改 vector 的大小和其中的元素。

【STL】vector的使用

【STL】vector的使用

resize 用于调整 vector 的大小,使其包含 n 个元素,能够对其中的值进行初始化,若未传参数则缺省为 0。

  • 如果n小于当前size,则内容将减少到其前n个元素,删除超出的元素,不更改capacity
  • 如果n大于当前size小于capacity,则通过在末尾插入所需数量的元素来扩展内容,以达到n的大小
  • 如果n大于当前capacity,将自动重新分配存储空间,再将元素填充至n个

使用这段代码便可以直接地观察到上述三种不同的情况。

int main()
{
	vector<int> v = { 1,2,3,4,5 };
	cout << v.size() << " " << v.capacity() << endl;
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.resize(20);
	cout << v.size() << " " << v.capacity() << endl;
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.resize(10);
	cout << v.size() << " " << v.capacity() << endl;
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	return 0;
}

 【STL】vector的使用

判空

【STL】vector的使用

通过 empty 这个接口可以得知当前这个 vector 是否为空,换言之就是 size 是否等于 0。

 【STL】vector的使用

访问数据

下标访问

库中对 [ ] 运算符进行了重载,因此可以使用下标对 vector 的元素直接进行访问。

【STL】vector的使用

 结合前面的 size 接口便可以简单实现下标遍历 vector。

【STL】vector的使用

边界访问

虽然说用下标直接访问就十分的方便了,但库中还有两个接口用于边界值的访问。

通过这两个接口可以直接访问 vector 中的第一个与最后一个元素。

【STL】vector的使用

 【STL】vector的使用

数据修改

讲完数据访问,之后便是对 vector 之中的元素进行修改的操作了。

尾插尾删

库中有两个接口分别是 push_back 和 pop_back 分别对应尾插和尾删的功能。

【STL】vector的使用【STL】vector的使用

 可以使用如下代码看看接口的效果。

int main()
{
	vector<int> v = { 1,2,3,4,5 };  //原数组
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.pop_back();         //尾删
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.push_back(8);       //尾插
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	return 0;
}

 【STL】vector的使用

指定位置插入删除

【STL】vector的使用

 insert 支持让我们在指定的位置插入元素,同时有三种插入方式供使用者选择。

  • 指定位置插入一个val
  • 指定位置插入n个val
  • 指定位置插入迭代器区间

可以通过下面的实例代码看看实际使用的效果。

int main()
{
	vector<int> v = { 1,2,3,4,5 };  //原数组
	vector<int> v1 = { 8,9,10 };
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.insert(v.begin() + 3, 6);   //插入单个值
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.insert(v.begin() + 4, 3, 7);  //插入n个值
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.insert(v.begin() + 6, v1.begin(), v1.end());   //插入一段区间
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	return 0;
}

 【STL】vector的使用

之后我们可以使用 erase 删除任意位置的元素。可以给定一个迭代器位置,或是一个迭代器区间,删除该区间内的元素。

【STL】vector的使用

值得注意的时,传入的迭代器区间其实是左闭右开的,因此迭代器 last 指向的那个元素不会被删除。

int main()
{
	vector<int> v = { 1,2,3,4,5 };  //原数组
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.erase(v.begin());   //删除第一个元素
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	v.erase(v.begin() + 1, v.begin() + 3);  //删除[3,5)
	for (auto it : v)
	{
		cout << it << " ";
	}
	cout << endl;
	return 0;
}

 【STL】vector的使用

迭代器失效 

若我们尝试连续插入多个数据的时候,可能会出现这样子的错误。

【STL】vector的使用   【STL】vector的使用

这是由于当我们不断插入数据的时候,如果出现容量不足的情况就会进行扩容,而扩容大概率不会直接在原地扩容。因此在异地开辟了一块新空间,并将原来的元素拷贝过去,从而达到扩容的效果。

此时,我们原先拿到的迭代器中存的仍是原来空间的地址,而原来那块空间已被释放,因此该迭代器中的地址便成了野指针

换言之,这个迭代器就失效了。那我们如何解决这个问题呢?其实 insert 是有一个返回值的,只不过我们之前忽略了它。

【STL】vector的使用

即,会返回指向插入的第一个元素的迭代器,因此我们只需要每次将 insert 的返回值再传回给我们的迭代器,就能够避免迭代器失效的问题。

int main()
{
	vector<int> v = { 1,2,3 };
	auto it = v.begin() + 2;
	for (int i = 0; i <= 20; i++)
	{
		it = v.insert(it, i);
	}
	return 0;
}

同样的现象也会出现在 erase 上,其返回的迭代器是指向删除区间的下一个位置。

清空

我们还可以使用 clear 清空 vector 中的所有元素,本质上就是将 vector 的 size 大小改成 0 即可。

【STL】vector的使用

【STL】vector的使用

交换

之前在 string 我们也讲过,容器之间的交换并不需要完全的拷贝,而是直接交换类中的指针即可。

因此 vector 中的这个交换函数,自然比原生的交换函数效率要来得高

【STL】vector的使用

 【STL】vector的使用

查找数据

虽然 vector 的库中并没有查找的这个函数,但是在算法库中为我们准备了一个 find 函数可以进行查找。

【STL】vector的使用

传入一个迭代器区间,再输入要查找的值即可,找到了则返回指向该元素的迭代器,反之则返回该容器的 end。

int main()
{
	vector<int> v1 = { 1,2,3,4,5 };
	cout << *find(v1.begin(), v1.end(), 4);
	return 0;
}

这个函数通过使用迭代器因而同时支持了多种容器,使用起来相当方便。

vector<char>可以代替string吗

vector 是一种泛型编程,同时支持 int 和 double 等不同类型的存储,而这些存储形式一般用不到 string 之中的某些接口,比如 += 、逻辑运算等。

可以这么说,string 这个容器是专门针对存储字符类型的,因此其种的接口也是专门适用于处理字符串的,而 vector 需要考虑的是如何支持各种类型都能够存储其中而舍弃了 string 之中的部分操作。


好了,今天使用 vector 的讲解到这里就结束了,如果这篇文章对你有用的话还请留下你的三连加关注文章来源地址https://www.toymoban.com/news/detail-449689.html

到了这里,关于【STL】vector的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包