目录

一、vector简介

二、vector的使用

三、vector的空间增长问题

reserve和resize

四、vector的迭代器使用

begin和end

rbegin和rend

五、vector的增删查改

push_back和pop_back

insert和erase

find函数

六、元素访问

七、vector迭代器失效问题

迭代器失效解决方法


一、vector简介

STL 中的 vector是 C++ 标准库中最核心的动态数组容器,用于替代原始数组,提供自动内存管理和丰富功能。

核心接口速查

// 构造
vector<int> vec;                // 空vector
vector<int> vec(100);           // 100个0
vector<int> vec(100, 5);        // 100个5

// 元素访问
vec[0] = 10;                    // 无边界检查
vec.at(0) = 10;                 // 带边界检查(越界抛异常)
int* p = vec.data();            // 获取底层数组指针

// 容量操作
vec.reserve(1000);              // 预分配内存(不初始化)
vec.resize(50);                 // 改变元素数量
vec.shrink_to_fit();            // 释放多余内存

// 增删元素
vec.push_back(10);               // 尾部插入
vec.pop_back();                 // 尾部删除
vec.insert(vec.begin()+2, 20);  // 指定位置插入
vec.erase(vec.begin()+1);        // 删除指定位置

// 工具函数
vec.empty();                     // 是否为空
vec.size();                      // 实际元素数量
vec.capacity();                  // 当前内存容量

vector是 STL 中综合性能最优的通用容器,适用于 >90% 需动态数组的场景。其核心优势在于随机访问性能 + 缓存局部性 + 自动内存管理,是现代 C++ 高性能编程的基础设施。

二、vector的使用

构造

1: 构造一个某类型的空容器。

vector<int> vec;                // 空vector

2: 构造一个含有n个val的某类型容器。

vector<int> vec(100, 5);        // 100个5

3:拷贝构造

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

4:使用迭代器拷贝构造某一段内容

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

vector存储的类型很多也可以是自定义类型

int main()
{
	vector<string> vstr;  //数组里存放的是string类
	string s1 = "张三";   
	vstr.push_back(s1);
	vstr.push_back("李四"); //隐式类型转换
	return 0;
}

三、vector的空间增长问题

容量空间 接口说明
size 获取数据个数
capacity 获取容量大小
empty 判断是否为空
reserve(重点) 改变vector的capacity
resize(重点) 改变vector的size

size和capacity

#include <iostream>
#include <vector>
using namespace std;

int main()
{
	vector<int> vec(100, 5);
	cout << vec.size() << endl; //获取当前容器中的有效元素个数
	cout << vec.capacity() << endl; //获取当前容器的最大容量
	return 0;
}

reserve和resize

通过reserse函数改变容器的最大容量,resize函数改变容器中的有效元素个数。

reserve规则:
 1、当所给值大于容器当前的capacity时,将capacity扩大到该值。
 2、当所给值小于容器当前的capacity时,什么也不做。

resize规则:
 1、当所给值大于容器当前的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为0。
 2、当所给值小于容器当前的size时,将size缩小到该值。

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> v(5, 2);
	cout << v.size() << endl; //5
	cout << v.capacity() << endl; //5
	v.reserve(10); //改变容器的capacity为10,size不变
	cout << v.size() << endl; //5
	cout << v.capacity() << endl; //10
	v.resize(8); //改变容器的size为8
	cout << v.size() << endl; //8
	cout << v.capacity() << endl; //10
	return 0;
}

empty

通过empty函数判断当前容器(size)是否为空。

int main()
{
	vector<int> vec(10, 2);
	cout << vec.empty() << endl;//0 非空
	vector<int> v;
	cout << v.empty() << endl;//1 空

	return 0;
}

四、vector的迭代器使用

vector iterator 的使用

iterator的使用 接口说明
begin() 获取第一个数据位置的iterator/const_iterator
end() 获取最后一个数据的下 一个位置的iterator/const_iterator
rbegin 获取最后一个数据位置的reverse_iterator
rend() 获取第一个数据前一个位置的reverse_iterator

begin和end

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

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

rbegin和rend

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

int main()
{
	vector<int> v{0,1,2,3,4,5,6,7,8,9};
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//反向迭代器遍历容器
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend())
	{
		cout << *rit << " ";//9 8 7 6 5 4 3 2 1 0
		rit++;
	}
	cout << endl;
	return 0;
}

五、vector的增删查改

push_back和pop_back

通过push_back函数对容器进行尾插,pop_back函数对容器进行尾删。

int mian()
{
	vector<int> v{ 0,1,2,3,4};
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	v.pop_back();
	v.pop_back();
	//v 0 1 2
    return 0;
}

insert和erase

insert函数通过在指定位置的元素之前插入新元素来扩展向量,从而有效地将容器大小增加插入的元素数量。

通过erase函数可以删除所给迭代器位置的元素,或删除所给迭代器区间内的所有元素。

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

	//insert (iterator position, const value_type& val);
	v.insert(v.end(), 0); //在容器尾插入0

	//insert(iterator position, size_type n, const value_type & val);
	v.insert(v.begin(), 5, -1); //在容器开头插入5个-1

	//erase (iterator position);
	v.erase(v.begin()); //删除容器中的第一个元素

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

	return 0;
}

find函数

template <class InputIterator, class T>
   InputIterator find (InputIterator first, InputIterator last, const T& val);

find函数共三个参数,前两个参数确定一个迭代器区间(左闭右开),第三个参数确定所要寻找的值。
find函数在所给迭代器区间寻找第一个匹配的元素,并返回它的迭代器,若未找到,则返回所给的第二个参数。

int main()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	vector<int>::iterator pos = find(v.begin(), v.end(), 2); //获取值为2的元素的迭代器

	v.insert(pos, 10); //在2的位置插入10
	//1 10 2 3 4
	pos = find(v.begin(), v.end(), 3); //获取值为3的元素的迭代器

	v.erase(pos); //删除3
	//1 2 10 4
	return 0;
}

六、元素访问

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

int main()
{
	vector<int> v(10, 1);
	//使用“下标+[]”的方式遍历容器
	for (size_t i = 0; i < v.size(); i++)
	{
		v[i] = i;
		cout << v[i] << " ";
	}
	cout << endl;
	return 0;
}

七、vector迭代器失效问题

迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对 指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器 底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即 如果继续使用已经失效的迭代器,程序可能会崩溃)。

1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、 assign、push_back等。

#include <iostream>
using namespace std;
#include <vector>
int main()
{
	vector<int> v{ 1,2,3,4,5,6 };
	auto it = v.begin();
	// 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
   // v.resize(100, 8);
	// reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层量改变
		// v.reserve(100);
		 // 插入元素期间,可能会引起扩容,而导致原空间被释放
		// v.insert(v.begin(), 0);
		 // v.push_back(8);
		 // 给vector重新赋值,可能会引起底层容量改变
		v.assign(100, 8);
	/*
   出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释
   放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块
   已经被释放的空间,而引起代码运行时崩溃。
   解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给
   it重新赋值即可。
   */
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

迭代器失效解决方法

使用迭代器时,永远记住一句话:每次使用前,对迭代器进行重新赋值。

int main()
{
	vector<int> v{ 1,2,3,4,5,6 };
	auto it = v.begin();
	v.assign(100, 8);
    //这里重新定位了it让其指向新空间的起始
	it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	return 0;
}

Logo

欢迎加入西安开发者社区!我们致力于为西安地区的开发者提供学习、合作和成长的机会。参与我们的活动,与专家分享最新技术趋势,解决挑战,探索创新。加入我们,共同打造技术社区!

更多推荐