首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C++STL】《别再踩坑!vector 用不对还崩代码?这篇帮你避掉 90% 的坑》

【C++STL】《别再踩坑!vector 用不对还崩代码?这篇帮你避掉 90% 的坑》

作者头像
用户11960591
发布2025-12-23 15:47:59
发布2025-12-23 15:47:59
980
举报

前言:在前面的文章中我们已经介绍了string的用法及其模拟实现,本篇文章就进入到vector的学习。学习STL还是遵循学会使用,理解底层的步骤学习,所以本篇文章会介绍vector的使用。

一、vector的介绍

1.1vector的概念

Vector是一种动态数组,能够自动管理内存并根据需要调整大小。它属于C++标准模板库(STL),提供高效的随机访问和尾部插入/删除操作。

1.2vector的特性

  1. 动态扩容:当元素数量超过当前容量时,Vector会自动分配更大的内存空间(通常按固定比例扩容,如2倍)。
  2. 连续存储:元素在内存中连续存放,支持通过下标([]或at())直接访问。
  3. 迭代器支持:提供随机访问迭代器,兼容STL算法(如sort、find)。

二、vector核心接口的使用

2.1构造相关的接口使用

构造函数声明

接口说明

vector()

无参构造(默认构造函数)

vector(size_type n, const value_type& val = value_type())

构造并初始化 n 个值为 val 的元素(val 默认为 value_type 的默认值)

vector(const vector& x)

拷贝构造(通过另一个 vector 对象 x 初始化)

vector(InputIterator first, InputIterator last)

使用迭代器范围 [first, last) 进行初始化构造

要点说明: 无参构造:创建空的容器,通常用于后续动态添加元素。 带数量及默认值的构造:预先分配空间并填充指定值,适合需要预初始化的情况。 拷贝构造:深拷贝另一个 vector 的所有元素,独立于原对象。 迭代器范围构造:支持从其他容器的迭代器(如数组、list 等)初始化,灵活性高。

代码示例:

代码语言:javascript
复制
#include<vector>
#include<iostream>
using namespace std;
int main()
{
	//默认构造
	vector<int> v1;
	//使用n个值构造初始化
	vector<int> v2(10, 1);//用10个1初始化v2
	for (auto e : v2)
	{
		cout << e<< " ";
	}
	cout << endl;
	//拷贝构造
	vector<int> v3(v2);//v2拷贝给v3
	for (auto e : v3)
	{
		cout << e << " ";
	}
	cout << endl;
	//使用迭代器初始化
	vector<int>::iterator it = v2.begin();
	vector<int> v4(v2.begin(), v2.end());
	for (auto e : v4)
	{
		cout << e << " ";
	}
	return 0;

}

运行结果:

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

2.2另一种初始化方式使用initializer_list初始化

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
int main()
{
	//初始化列表初始化就是像数组一样使用花括号初始化
	int a[] = { 10, 20, 30 };
	auto il1 = { 10, 20, 30 };
	auto il2 = { 10, 20, 30,1,1,1,1,1,1,1 };
	cout << typeid(il1).name() << endl;//使用typeid查看真实的类型是			initializer_list
	//cout << il1.begin() << endl; li1与a(整型)的地址相似说明它们类型是一样的
	//cout << a << endl;

	vector<int> v1 = { 10, 20, 30 };
	vector<int> v2 = { 10, 20, 30,1,1,1,1,1,1,1 };
	for (const auto& e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

使用花括号初始化的逻辑:花括号的内容会被隐式类型转化成initializer_list类型,然后再调用对应的构造函数。

2.3vector迭代器的使用

方法

返回类型

作用描述

begin()

iterator/const_iterator

获取容器第一个数据位置的迭代器(非const版本可能修改元素)

end()

iterator/const_iterator

获取容器最后一个数据的下一个位置的迭代器(哨兵位,不可解引用)

rbegin()

reverse_iterator

获取容器最后一个数据位置的逆向迭代器(实际是end()-1的封装)

rend()

reverse_iterator

获取容器第一个数据前一个位置的逆向迭代器(实际是begin()-1的封装)

要点说明: begin() 和 end():通常用于正向遍历容器。 rbegin() 和 rend():用于逆向遍历容器。 const 版本:如 cbegin()/cend() 返回 const_iterator,确保遍历时不修改元素。

代码示例:

代码语言:javascript
复制
#include<vector>
#include<iostream>
using namespace std;
int main()
{
	vector<int> v1 = { 1, 2, 3 };
	//正向迭代器
	vector<int>::iterator it1 = v1.begin();
	while (it1 != v1.end())
	{
		cout << *it1<<" ";
		++it1;
	}
	cout << endl;
	//反向迭代器
	vector<int>::reverse_iterator it2 = v1.rbegin();
	while (it2 != v1.rend())
	{
		cout << *it2<<" ";
		++it2;
	}
	cout << endl;
	//范围for (推荐)
	for (auto e : v1)
	{
		cout << e <<" ";
	}
}

运行结果:

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

迭代器图解:

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

2.4vector的空间相关的接口

接口名称

功能描述

备注

size_type size() const

获取当前存储的数据个数

实际元素数量

size_type capacity() const

获取当前分配的容量大小

预分配内存空间大小

bool empty() const

判断容器是否为空

等价于size==0

void resize (size_type n, value_type val = value_type());

改变容器的实际元素数量(size)

可能影响capacity

void reserve (size_type n)

改变容器的预分配容量(capacity)

不影响现有元素

要点说明: vector的capacity的增容的倍数是看编译器,例如vs下是二倍扩容,而g++下是1.5倍扩容,具体扩容倍数是根据需求来定的!

代码示例:

代码语言:javascript
复制
#include<vector>
#include<iostream>
using namespace std;
int main()
{
	vector<int> v1(10, 11);
	//有效数据个数
	cout << v1.size() << endl;
	//空间大小
	cout << v1.capacity() << endl;

	if (!v1.empty())//判断vector是否为空
	{
		for (auto e : v1)
		{
			cout << e << " ";
		}
	}
	cout << endl;
	//扩容 扩容的空间使用6来填充
	v1.resize(20, 6);
	cout <<"size:"<< v1.size() << endl;
	cout <<"capacity:"<< v1.capacity() << endl;
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
	//resise缩容 
	v1.resize(5);//缩小的是有效数据个数
	cout << "size:" << v1.size() << endl;
	cout << "capacity:" << v1.capacity() << endl;
	
	vector<int> v2;
	v2.reserve(10);
	cout << "size:" << v2.size() << endl;
	cout << "capacity:" << v2.capacity() << endl;

	return 0;
}

运行结果:

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

三、vector的增删查改操作

接口名称

功能描述

备注

void push_back (const value_type& val)

在vector尾部插入元素

时间复杂度O(1)(均摊)

void pop_back()

删除vector尾部元素

不会返回被删除元素

find

在范围内查找指定值

需包含<algorithm>头文件,返回迭代器

iterator insert (iterator position, const value_type& val);

在指定迭代器位置前插入元素

可能导致迭代器失效

iterator erase (iterator position)

删除指定迭代器位置的元素

返回指向下一元素的迭代器

void swap (vector& x)

交换两个vector的存储空间

常数时间复杂度

reference operator[] (size_type n)

通过下标随机访问元素

不进行越界检查

要点说明: insert 与 erase 的返回值均为指向操作后位置的迭代器,需注意迭代器失效问题。(在实现部分讲) operator[] 和 at() 的区别在于后者会进行边界检查并抛出异常。 find采用的是算法库的find,传入的参数为一个迭代器区间,加上一个val(所要查找的值)。

代码示例:

代码语言:javascript
复制
#include<vector>
#include<iostream>
using namespace std;
int main()
{
	vector<int> v1;
	//尾插
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	cout << "size:" << v1.size() << endl;
	//删除数据
	v1.pop_back();
	cout << "size:" << v1.size() << endl;

	//insert 效率较低涉及数据的移动
	vector<int> v2;
	v2.push_back(1);
	v2.push_back(2);
	v2.push_back(3);
	v2.push_back(5);
	v2.insert(v2.begin() + 3, 100);
	//(算法库的)find+insert
	auto it = find(v2.begin(), v2.end(), 2);
	if (it != v2.end())
	{
		//在该迭代器位置处插入50
		v2.insert(it, 50);
	}

	//erase 效率较低涉及数据的移动
	v2.erase(v2.begin() + 3);//删除下标为3位置处的数据
	//find+erase
	auto it1 = find(v2.begin(), v2.end(), 100);
	if (it1 != v2.end())
	{
		v2.erase(it1);
	}
	//下标访问
	cout<<v2[5]<<endl;
	return 0;
	}

3.1vector对自定义类型的操作

代码语言:javascript
复制
struct A
{
	A(int a1, int a2)
		:_a1(a1)
		,_a2(a2)
	{
		cout << "A(int a1, int a2)" << endl;
	}
	A(const A& aa)
		:_a1(aa._a1)
		,_a2(aa._a2)
	{
		cout << "A(const A& aa)" << endl;
	}
	int _a1;
	int _a2;
};
int main()
{
	//push_back与emplace_back效率的比较
	vector<A> v2;
	A aa1(1, 1);
	v2.push_back(aa1);
	cout << endl;
	v2.push_back(A(2,2));
	cout << endl;

	v2.push_back({3,3});
	cout << endl;

	cout << "**************************" << endl;

	v2.emplace_back(aa1);
	cout << endl;

	v2.emplace_back(A(2, 2));
	cout << endl;
	
	v2.emplace_back( 3,3 );
	//emplace_back不支持初始化列表初始化
	//v2.emplace_back({ 3,3 });

	//遍历自定义类型可以使用范围for也可以使用结构化绑定
	//C++11 范围for
	for (auto& aa : v2)
	{
		cout << aa._a1 << ":" << aa._a2 << endl;
	}

	// C++17 结构化绑定
	//auto [x, y] = aa1;//x y为A类型的成员变量 x y 的名字可以任取
	for (auto& [x, y] : v2)
	{
		cout << x << ":" << y << endl;
	}
}

以上就是本篇文章的所有内容了,感谢各位大佬观看,制作不易还望各位大佬点赞支持一下!有什么问题可以加我私信交流!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、vector的介绍
    • 1.1vector的概念
    • 1.2vector的特性
  • 二、vector核心接口的使用
    • 2.1构造相关的接口使用
    • 2.2另一种初始化方式使用initializer_list初始化
    • 2.3vector迭代器的使用
    • 2.4vector的空间相关的接口
  • 三、vector的增删查改操作
    • 3.1vector对自定义类型的操作
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档