(C++) vector认识与应用 迭代器 默认成员函数 容量函数 [ ]接口 内部数据访问与修改

# 0 vector

vector是数据库提供的容器之一,本质上是顺序表。
内部成员变量是三个所存储数据类型的指针。

// 分别是:
	iterator _start; // 指向数据空间的开始
	iterator _finish; // 指向最后一个有效数据的下一个位置
	iterator _endOfStorage; // 指向存储容量的尾

要使用vector,需要包含头文件:

#include <vector>

vector是一个类模板,使用时需要显式实例化,
指明内部存储的数据类型。

// 例如:
	vector<int> v1;
	vector<double> v2;
	vector<string> v3;

# 1 迭代器

vector的迭代器就是原生的指针。
这是因为vector本质上是顺序表,底层空间是连续的。

为了规范,为了与所有的容器保持一致,
内部都将迭代器类型重命名为iterator,
const对象的迭代器重命名为const_iterator。

反向迭代器等,下面就不提了。

# 1.1 begin()

在这里插入图片描述
支持const与非const对象调用。
返回指向数据空间起始位置的迭代器。

# 1.2 end()

在这里插入图片描述
支持const对象与非const对象调用。
返回指向最后一个有效数据的下一个位置的迭代器。
对这个位置的迭代器解引用是没有意义的,可能是无效的数据,甚至可能越界。

# 2 默认成员函数

# 2.1 构造函数

在这里插入图片描述
共有三种构造函数。
分别是无参的构造函数;
创建有n个有效数据,并初始化为value的构造;
用一个迭代器区间来构造。

# 2.1.1 无参的默认构造

	vector<int> v1;
	for (auto e : v1)
		{
			cout << e;
		}
		cout << endl;

在这里插入图片描述

这样创建出来的vector没有有效数据。
直接访问内部数据自然是什么都没有。
可以很方便的进行后续操作。

# 2.1.2 初始化n个数据的构造

传两个参数,第一个是有效数据的个数,第二个是用于初始化这些有效数据的值。
第二个参数有缺省值,为value_type()。
意思是调用该数据类型的默认构造来初始化。

为了使内置类型与类类型匹配格式,所以给内置类型也加上了默认构造。
具体是什么不重要,总之有就对了。

	vector<int> v2(10, 3);

	for (auto e : v2)
	{
		cout << e;
	}
	cout << endl;

在这里插入图片描述

# 2.1.3 迭代器区间构造

用一个迭代器区间来初始化,这个迭代器区间并不局限于vector的迭代器,也可以是其他容器的。

	vector<int> v2(10, 3);
	vector<int> v3(v2.begin(), v2.end());

	for (auto e : v3)
	{
		cout << e;
	}
	cout << endl;

在这里插入图片描述

# 2.2 拷贝构造

在这里插入图片描述
拷贝构造也算在构造函数内,这里第四个就是拷贝构造。
用另一个vector类型的对象来初始化。

	vector<int> v1(10, 5);
	vector<int> v2 = v1;

	for (auto e : v2)
	{
		cout << e;
	}
	cout << endl;

在这里插入图片描述

# 2.3 赋值重载

在这里插入图片描述
两个已经存在的vector类型对象,用一个赋值给另一个。

	vector<int> v1(10, 9);
	vector<int> v2;

	v2 = v1;

	for (auto e : v2)
	{
		cout << e;
	}
	cout << endl;

在这里插入图片描述

# 2.4 析构函数

vector的析构会释放开出来的这一块顺序表的空间。
没有什么可说的。

# 3 容量相关函数

# 3.1 size

返回对象内有效数据的个数。

# 3.2 capacity

返回对象内最大可存储有效数据的个数。

# 3.1 reserve

在这里插入图片描述

调整对象容量大小,如果目标容量小于原本容量,根据编译环境的不同,可能会缩小容量,或者是什么都不做。
如果大于原本容量,就会讲容量扩大至至少目标容量的大小,根据编译环境的不同,可能会更大。
无论哪种,reserve行为都不会影响有效数据。

void Test6()
{
	vector<int> v(10, 7);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;

// 目标容量大于原容量
	v.reserve(20);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;

// 目标容量小于原容量
	v.reserve(3);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;
}

在这里插入图片描述
可以看到,有效数据始终没有变化;
目标容量大于原容量时扩容,否则容量不变。

# 3.1 resize

在这里插入图片描述
resize支持传两个参数。
第一个参数指定目标有效数据个数,有三种情况:

1.目标size小于原size:
会发生截断,只保留原有效数据的前目标size个。

2.目标size大于原size,小于等于原capacity:
空间足够,那么会填充数据,直至个数达到目标size,
用于填充的值就是第二个参数。
这个参数可以缺省,会调用数据类型的构造函数。

3.目标size大于原capacity:
这种情况就会扩容了,扩容完成后就相当于是第二种情况了,
会用第二个参数去填充。

void Test7()
{
	vector<int> v(10, 8);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;

	v.resize(3);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;

	v.resize(7);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;

	v.resize(11);
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e;
	}
	cout << endl << endl;
}

在这里插入图片描述
最后扩容的时候,到底扩容到多少是由编译器决定的,和前面提到的一样,并不一定是开的正好,可能会更大,就像这里。

# 4 内部数据访问与修改函数

# 4.1 [ ]重载

在这里插入图片描述
[ ]重载是vector最大的优势,能够随机且高效的访问数据。

void Test8()
{
	vector<int> v(10, 1);

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

在这里插入图片描述

# 4.2 尾插push_back

在这里插入图片描述
尾插是vector增加数据最常用的,也是最有效率的。
空间不足时,会自动扩容。

void Test9()
{
	vector<int> v(3, 4);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);
	v.push_back(60);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

在这里插入图片描述

# 4.3 尾删pop_back

在这里插入图片描述
简单从尾部删除数据,改变size,不改变capacity。

void Test9()
{
	vector<int> v(3, 4);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);
	v.push_back(60);

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	v.pop_back();
	v.pop_back();
	v.pop_back();

	cout << v.size() << endl;
	cout << v.capacity() << endl;
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

在这里插入图片描述

# 4.4 交换swap

在这里插入图片描述
简单的交换两个vector类型的对象。
没什么好说的。

# 4.5 任意位置插入insert

在这里插入图片描述

insert有三种重载:

1.在指定迭代器位置position插入数据val;

2.在指定迭代器位置position插入n个数据val;

3.在指定迭代器位置position插入一段迭代器区间内的数据。

void Test10()
{
	vector<int> v(5, 2);
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// 起始位置插入
	v.insert(find(v.begin(), v.end(), 2), 20);

	// 中间位置插入
	v.insert(find(v.begin(), v.end(), 2), 30);
	v.insert(find(v.begin(), v.end(), 2), 4, 40);

	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

在这里插入图片描述

# 4.6 任意位置删除erase

在这里插入图片描述
两种重载:
1.删除目标迭代器位置的数据;
2.删除一段迭代器区间内的数据。

void Test10()
{
	vector<int> v(5, 2);
	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// 起始位置插入
	v.insert(find(v.begin(), v.end(), 2), 20);

	// 中间位置插入
	v.insert(find(v.begin(), v.end(), 2), 30);
	v.insert(find(v.begin(), v.end(), 2), 4, 40);

	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;

	// 头删
	v.erase(find(v.begin(), v.end(), 20));

	v.erase(find(v.begin(), v.end(), 40), find(v.begin(), v.end(), 2));

	for (auto e : v)
	{
		cout << e << " ";
	}
	cout << endl << endl;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值