vector的应用练习

在这里插入图片描述
这是一个vector模板的声明,实际上实例化需要传入模板参数。

  • 第一个是他的参数类型,例如
    vector<int>,vector<char>,甚至一个二维数组vectoe<vector<int>>,vector<vector<char>>等。
  • 第二个参数是空间配置器,空间配置器就是内存池,从内存池里拿内存,避免反复从操作系统申请。
    不是直接new或malloc,而是从内存池这个中间商去拿,可以提高效率。作为参数就是可以让我们自定义自己的空间配置器,来替换STL默认的。

我们用的string是直接实例化好的一个模板类。我们目前所接触的string参数都是char类型,只是经过了typedef。
在这里插入图片描述

1. 构造函数

在这里插入图片描述
在这里插入图片描述

explict代表不允许隐式类型转换的发生,因为一个内存池变成vector对象,是很怪异的。

	//无参构造
	vector<int> v1;
	//构造10个空间初始化10个3
	vector<int> v2(10,3);
	//拷贝构造
	vector<int> v3(v2);

迭代器初始化构造需要注意的地方。

  1. 可以是其他类型的迭代器,但是属性必须和构造对象的属性相同。因为它实际上是一个模板
    传什么迭代器就会推演出什么迭代器,认为迭代器是一段区间(左闭右开)但是当迭代器解引用之后必须为同一类型。
    在这里插入图片描述
	//迭代器初始化构造
	vector<int> v4(v2.begin(), v2.end());
	list<int> l1(5,4);
	vector<int> v5(l1.begin(), l1.end());
    //原理
    while(first!=last)
    {
       push_back(*first);
       ++first;
    }

2. 遍历

2.1 []遍历

for (size_t i = 0; i < v2.size(); i++)
	{
		cout << v2[i] <<" ";
	}

在这里插入图片描述

2.2 迭代器遍历

与之前的string使用几乎一模一样

vector<int>::iterator it3 = v3.begin();
	while (it3 != v3.end())
	{
		cout << *it3;
		it3++;
	}

同样需要注意的是在函数内,由于我们不需要改变可以加const且对象是引用,所以我们需要使用const迭代器

void print(const vector<int>& v)
{
	vector<int>::const_iterator it3 = v.begin();
	while (it3 != v.end())
	{
		cout << *it3;
		it3++;
	}
}

反向迭代器倒着遍历,每次的迭代器对象是++,并不是–。

2.3 范围for

for(const auto& e:v3)
{
  cout<<v3<<" ";
}

替换成了迭代器。尽量传引用,不需要改变在加上const。因为v3可能是vector<string>,更有可能是vector<map<string,string>>等各种类型套一起,如果不加引用,e每次都深拷贝消耗太大太大。

3. 空间

3.1 resize

当n小于原有空间。将原有空间缩小为n。
在这里插入图片描述

//v3.resize(5,100);
v3.resize(5);

resize,当n大于原有空间时,开空间并且初始化。所以当n小于原有空间,即使你第二个参数传了值,也不会改变以前的值。

v3.resize(12,5);

在这里插入图片描述

3.2 reserve

先来看一个增容问题

	vector<int> v1;
	int sz = v1.capacity();
	for (size_t i = 0; i < 100; i++)
	{
		v1.push_back(i);
		if (sz != v1.capacity())
		{
			sz = v1.capacity();
			cout << "发生增容,现在vector的capacity为:"<<sz<< endl;
		}
	}

可以看出在vs编译器下几乎是以1.5倍取整一直增容。
在这里插入图片描述

同样的代码在Linux下是以2倍的增容。
在这里插入图片描述
没有什么大的区别,倍数小,增容次数频繁,倍数大就会有浪费空间,很正常。

所以其实当你知道也要开多大的空间时,你就直接调用reserve开空间。就不会有乱七八糟的扩容了
在这里插入图片描述

4. 增删改查

在这里插入图片描述

4.1 尾插与尾删

	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);
	v1.push_back(9);
	print(v1);
	v1.pop_back();
	print(v1);

在这里插入图片描述

4.2 查找

在这里插入图片描述
find太常见了,所以在std库中直接实现了一个模板。
在这里插入图片描述
返回一个迭代器,因为迭代器的区间是[firsr,last),所以返回last就代表没有找到。

	//也可以直接用auto pos=find(v1.begin(), v1.end(), 5);
	vector<int>::iterator pos = find(v1.begin(), v1.end(), 5);
	//返回v1.end()就说明没找到
	if(pos != v1.end())
	{
		cout << "找到了" << endl;
		*pos = 30;
	}
	for (auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

找到并且修改
在这里插入图片描述

5. 插入

学会find之后这些接口就容易多了,因为他们都是在find接口之后进行操作。只是需要时刻注意迭代器的左闭右开,也就是begin()是0下标,end()的下标是size,也就是最后一个元素的下一个位置

    vector<int>::iterator pos = find(v1.begin(), v1.end(), 5);
	//返回v1.end()就说明没找到
	if(pos != v1.end())
	{
		cout << "找到了" << endl;
		v1.insert(pos, 4);
	}
	for (auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

在这里插入图片描述

vector<int>::iterator pos = find(v1.begin(), v1.end(), 5);
	//返回v1.end()就说明没找到
	if(pos != v1.end())
	{
		cout << "找到了" << endl;
		/*v1.insert(pos, 4);*/
	}
	v1.erase(pos);
	for (auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

在这里插入图片描述
这里必须把insert注释掉,因为插入会引起迭代器失效的问题,pos本来指向5,由于插入了一个4,导致pos的指向发生变化,引起迭代器失效。也可能是空间不够,由于增容的时候步骤是,先扩容,拷贝原空间至扩容的空间,然后释放原空间,pos此时还指向这原空间,迭代器也会失效。以后还会详细进行讲解。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值