欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STL 之 vector

程序员文章站 2024-02-26 21:45:04
...

1、vector是表示可变大小数组的序列容器
2、vector存储元素是采用连续存储空间,可利用下标访问vector中的元素;
3、vector是一个能够存放任意类型的动态数组,能够增加和压缩数据;
4、vector是一个类模板,不是一种数据类型。可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此vector 等都是数据类型。

vector的定义

1、初始化vector对象

构造函数声明 接口说明
vector< T > v1 无参构造
vector< T > v2(n, val) 构造并初始化n个val
vector< T > v3(v2) 拷贝构造
vector< T > V4(v3.begin(),v3.end()) 使用迭代器进行初始化构造

具体使用

int main()
{
	vector<int> v1;//无参构造
	vector<int> v2(5, 3);//构造并初始化5个3
	vector<int> v3(v2);//拷贝构造v2
	vector<int> v4(v3.begin(), v3.end());//迭代器构造v3
	
	system("pause");
	return 0;
}

查看输出结果
STL 之 vector
注意事项:
1、在构造非空vector对象时,必须给出初始化元素的值;
2、在进行拷贝构造时,这两个 vector 对象必须是同一种元素类型。


2、vector iterator 的使用

iterator的使用 接口说明
begin() + end() 获取第一个元素的位置及最后一个元素的下一个位置
rbegin() + rend() 获取最后一个元素的位置及第一个元素的前一个位置

举个栗子:
用下面这列数据说明这几个接口的位置

1 2 3 4 5 6 7 8 9 10 11 12 13 14

STL 之 vector
迭代器可以遍历打印vector数组的值,还可以修改数组中元素的值;
还可以利用反向迭代器(reverse_iterator)来遍历打印vector数组元素的值。

打印vector数组

void printvector(vector<int> v)
{
#if 0
	//方法一:用范围for遍历打印
	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
#elif 0
	//方法二:const对象使用const迭代器进行遍历打印
	vector<int>::const_iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
#endif
	//反向迭代器,反向遍历打印
	vector<int>::reverse_iterator it = v.rbegin();
	while (it != v.rend())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

3、vector的空间大小

容量空间 接口说明
size() vector中元素的个数
capacity() 获取分配空间的大小
empty() vector中没有元素返回true,否则返回false
resize() 修改size的大小
reserve() 修改capacity的值

注:
size与capacity的区别
size是计算当前vector中元素的个数,即真实占用的空间;
capacity是计算vector预分配的空间大小,即可以存储元素的最大空间大小。

resize与reserve的区别
resize()既要开辟空间也要进行初始化,修改size的大小,容器内的对象内存空间是真正存在的;
reserve()只负责开辟空间,改变预留空间的大小,对象内存空间并不是真实的存在。

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的


4、vector的增删查改

vector的增删查改 接口说明
push_back() 尾插
pop_back() 尾删
find() 查找
insert() 在pos前插入
erase() 删除pos位置的数据
swap() 交换两个vector的数据空间
operator[] 中括号重载,向数组一样访问

以代码为例

insert的三种方法

int main()
{
	vector<int> v = { 2,3,4,5 };

	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
#if 0
	//v.insert(pos,val); 在pos前插入元素的值val
	v.insert(pos, 6);//在pos前插入元素6
	for (auto &e : v)
	{
		cout << e << " ";
}
	cout << endl;
#elif 0
	//v.insert(pos, n, val);//在pos前插入n个val
	v.insert(pos, 3, 5);//在pos前插入3个5
	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
#endif
	vector<int> v2 = { 1,2,3,4,5 };
	//v.insert(pos, v2.begin(), v2.end());在pos前插入一段元素的值
	v.insert(pos, v2.begin(), v2.end());
	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

erase的两种方法

int main()
{
	vector<int> v = { 2,3,4,5 };

	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	
	vector<int>::iterator pos = find(v.begin(), v.end(), 3);
#if 0
	v.erase(pos);//删除pos位置的元素
	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
#endif
	//v.erase(arr.begin(),arr.end()); 删除数组中的一段元素
	v.erase(v.begin() + 2,v.end());

	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

重点:迭代器失效问题
使用insert 和erase时会导致迭代器失效,例如下面这个例子:

int main()
{
	vector<int> v = { 2,3,4,6,7,8 };
	for (auto &e : v)
	{
		cout << e << " ";
	}
	cout << endl;

	vector<int>::iterator pos = find(v.begin(), v.end(), 6);
	
	//在pos处删除数据,会导致迭代器失效
	//因为把pos处的元素删除后,pos还指向原来的空间,此时的元素已经被删除,
	//空间也被释放,从而导致迭代器失效。
	v.erase(pos);//删除pos处的元素
	cout << *pos << endl;//此时pos位置处的元素不能访问,即迭代器失效

	// 在pos位置插入数据,导致pos迭代器失效。
	// insert会导致迭代器失效,是因为insert可能会导致增容,
	//增容后pos还指向原来的空间,而原来的空间已经释放了。
	pos = find(v.begin(), v.end(), 3);
	v.insert(pos, 30);
	cout << *pos << endl; // 此处会导致非法访问
	system("pause");
	return 0;
}

总结:
insert导致迭代器失效:insert可能会导致增容,增容后pos还指向原来的空间,而原来的空间已经释放了,从而导致迭代器失效;
erase导致迭代器失效:erase把pos处的元素删除后,pos还指向原来的空间,此时的元素已经被删除,空间也被释放,从而导致迭代器失效。

相关标签: C++知识总结