
🔥草莓熊Lotso: 个人主页
❄️个人专栏:《C++知识分享》《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受。
🎬 博主简介:
目录
[一. vector是什么?一段话搞懂核心定位](#一. vector是什么?一段话搞懂核心定位)
[二. vector核心接口:必学的几个高频操作](#二. vector核心接口:必学的几个高频操作)
[2.1 定义和初始化(构造函数)](#2.1 定义和初始化(构造函数))
[2.2 迭代器:遍历 vector 的 "万能工具"](#2.2 迭代器:遍历 vector 的 "万能工具")
[2.3 空间管理:size、capacity 与扩容策略](#2.3 空间管理:size、capacity 与扩容策略)
[2.4 增删查改:日常开发高频操作](#2.4 增删查改:日常开发高频操作)
[三. vector 实战:OJ 算法题中的高频用法](#三. vector 实战:OJ 算法题中的高频用法)
[3.1 只出现一次的数字](#3.1 只出现一次的数字)
[3.2 杨辉三角](#3.2 杨辉三角)
前言:
在 C++ STL 容器中,vector 是最常用、最灵活的动态数组容器,既能像普通数组一样高效访问元素,又能自动扩容适配数据量变化。无论是日常开发还是算法刷题(OJ 场景,vector 都是高频工具。本文将从 "能用" 到 "会用",系统讲解 vector 的核心接口、使用技巧与避坑要点,帮你彻底掌握这个 "万能容器"。
一. vector是什么?一段话搞懂核心定位
vector 本质是动态大小的数组,底层通过连续内存存储元素,支持:
- 随机访问(像数组一样用[ ]访问,时间复杂度为 O(1)))。
- 自动扩容(元素超过容量时,自动分配更大内存并转移数据)。
- 灵活增删(尾插,尾删高效,中间插入/删除需移动元素)。
简单说:vector综合了普通数组的便捷性+动态扩容的灵活性。
二. vector核心接口:必学的几个高频操作
- 我们有了前面学习 string 的基础,再来学习 vector 就轻松很多了,而且也不需要记住所有接口,重点掌握 "定义、迭代器、空间管理、增删查改" 四大类核心接口,即可覆盖 90% 以上场景。
--由于vector没有重置流插入流提取,所以我们这里自己实现一个打印,其实这里的遍历打印操作是跟string差不多的,直接看代码就行。
cpp
void Print(const vector<int>& v)
{
//1.下标
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
//2.范围for
//for (auto e : v)
//{
// cout << e << " ";
//}
//cout << endl;
//3.迭代器
//vector<int>::const_iterator it = v.begin();
//while (it != v.end())
//{
// cout << *it << " ";
// it++;
//}
//cout << endl;
}
2.1 定义和初始化(构造函数)
vector 提供了4种常用构造方式,我们可以根据不同场景来选择
构造函数声明 | 接口说明 | 代码示例 |
---|---|---|
vector()(重点) | 无参构造,创建空 vector | vector<int> v;(空容器,size=0,capacity=0) |
vector(size_type n, val) | 构造并初始化 n 个 val | vector<int> v(5, 3);(含 5 个 3,size=5,capacity=5) |
vector(const vector& x)(重点) | 拷贝构造,复制另一个 vector | vector<int> v2(v1);(v2 是 v1 的副本) |
vector(iterator first, iterator last) | 迭代器初始化,复制区间元素 | vector<int> v(a, a+5);(复制数组 a [0]~a [4]) |

--这里补充了一个C++11之后的方式,下面的代码里面会有
代码演示:
cpp
void test_vector1()
{
vector<int> v1;
vector<int> v2(10,1);
vector<int> v3(v2.begin(),v2.end());
string s1("xxxxxxxxxxxxxxxxxxxxxxxxxx");
//用其它类型的迭代器,这两个类型必须要可以转换
vector<int> v4(s1.begin(), s1.end());
vector<int> v5(v3);
//C++11
//vector<int> v6({ 1,2,3,4,5 });
vector<int> v6 = { 1,2,3,4,5 };
vector<int> v7={ 1,2,3,4,5,1,1,1,1,1};
//其实是这样
auto il = { 10,20,30,1,2,2 };
for (auto e : il)
{
cout << e << " ";
}
cout << endl;
Print(v2);
Print(v4);
Print(v6);
Print(v7);
}
int main()
{
test_vector1();
}

2.2 迭代器:遍历 vector 的 "万能工具"
- 迭代器是访问容器元素的通用接口,vector 的迭代器本质是 "封装的指针",支持遍历、取值、移动等操作。
核心迭代器接口如下:
迭代器接口 | 接口说明 | 代码示例(遍历 vector) |
---|---|---|
begin() | 获取第一个元素的迭代器 | auto it = v.begin();(指向 v [0]) |
end() | 获取最后一个元素下一位的迭代器 | while (it != v.end()) { ... } |
rbegin() | 获取最后一个元素的反向迭代器 | auto rit = v.rbegin();(指向 v [size-1]) |
rend() | 获取第一个元素前一位的反向迭代器 | while (rit != v.rend()) { ... } |
--下标访问下面也会演示,其实就是上面展示过的那个Print函数
代码演示:
cpp
void Print(const vector<int>& v)
{
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
//for (auto e : v)
//{
// cout << e << " ";
//}
//cout << endl;
//vector<int>::const_iterator it = v.begin();
//while (it != v.end())
//{
// cout << *it << " ";
// it++;
//}
//cout << endl;
}
2.3 空间管理:size、capacity 与扩容策略
- vector 的 "空间" 分为 size(有效元素个数)和 capacity(最大可容纳元素个数,不含结束标志),理解两者区别是避免扩容开销的关键。
核心空间接口:
空间接口 | 接口说明 | 代码示例 |
---|---|---|
size() | 获取有效元素个数 | cout << v.size();(v 有 5 个元素则输出 5) |
capacity() | 获取容量大小 | cout << v.capacity();(容量可能大于 size) |
empty() | 判断是否为空(size==0) | if (v.empty()) { ... } |
reserve(n)(重点) | 扩容到 n(仅开辟空间,不初始化) | v.reserve(100);(提前扩容到 100,避免后续多次扩容) |
resize(n, val)(重点) | 调整 size 到 n(缺省用 0 填充) | v.resize(5, 2);(size=5,不足则补 2,超出则截断) |
关键:vector 扩容策略
vector 扩容时会分配新内存 、迁移旧元素 、释放旧内存,这个过程耗时较高。不同编译器扩容倍数不同:
- VS:1.5 倍扩容(如 capacity 从 4→6→9→13...);
- G++:2 倍扩容(如 capacity 从 4→8→16→32...)。

避坑建议:若已知元素个数,提前用 reserve(n) 扩容,避免边插入边扩容的效率损耗。
示例:
cpp
void test_vector2()
{
vector<int> v1;
//const int n=10000000;
const int n = 100;
//v1.reserve(n);
size_t old = v1.capacity();
//cout << v1.capacity() << endl;
size_t begin = clock();
for (size_t i = 0; i < n; i++)
{
v1.push_back(i);
/*if (old != v1.capacity())
{
cout << v1.capacity() << endl;
old = v1.capacity();
}*/
}
size_t end = clock();
cout << end - begin << endl;
vector<int> v2;
v2.resize(100, 1);
Print(v2);
}
int main()
{
//test_vector1();
test_vector2();
}
2.4 增删查改:日常开发高频操作
- vector 的增删查改接口设计简洁,重点关注 "尾插 / 尾删" 的高效性和 "中间插入 / 删除" 的注意事项。
增删查改接口 | 接口说明 | 代码示例 | 时间复杂度 |
---|---|---|---|
push_back(val)(重点) | 尾插元素 val | v.push_back(5); | O (1)(无扩容时)/ O (n)(需扩容时) |
pop_back()(重点) | 尾删最后一个元素 | v.pop_back(); | O (1)(仅修改 size,不释放空间) |
insert(pos, val) | 在 pos 迭代器前插入 val | v.insert(v.begin()+2, 6); | O (n)(需移动 pos 后元素) |
erase(pos) | 删除 pos 迭代器指向的元素 | v.erase(v.begin()+1); | O (n)(需移动 pos 后元素) |
--还要emplace_back等这些,下面演示会有,先了解即可,后面再讲
代码演示:
cpp
void test_vector3()
{
vector<int> v1 = { 1,2,3,4,5 };
v1.push_back(6);
Print(v1);
v1.insert(v1.begin(), 0);
Print(v1);
v1.insert(v1.begin() + 3, 0);
Print(v1);
v1.erase(v1.begin());
Print(v1);
v1.erase(v1.begin() + 3);
Print(v1);
}
//template <class T>
//class vector
//{
//private:
// T* _a;
// size_t _size;
// size_t _capacity;
//};
struct AA
{
int _a1 = 1;
int _a2 = 1;
AA(int a1 = 1, int a2 = 1)
:_a1(a1)
,_a2(a2)
{ }
};
void test_vector4()
{
AA aa1 = { 0,0 };
vector<AA> v = { aa1,{1,1},{2,2},{3,3} };
auto it = v.begin();
while (it != v.end())
{
cout << it->_a1 << ":" << it->_a2 << endl;
++it;
}
cout << endl;
v.push_back(aa1);
v.emplace_back(aa1);
//推荐这样用
//但是这两种交替不行
v.emplace_back(1, 1);
v.push_back({ 2,2 });
it = v.begin();
while (it != v.end())
{
cout << it->_a1 << ":" << it->_a2 << endl;
++it;
}
cout << endl;
}
int main()
{
//test_vector1();
//test_vector2();
test_vector3();
test_vector4();
}

三. vector 实战:OJ 算法题中的高频用法
- vector 是算法刷题的 "主力容器",以下 3 道经典 OJ 题,覆盖 vector 的核心使用场景。
3.1 只出现一次的数字
题目链接:
题目描述:

题目示例:

C++算法代码:
cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret=0;
for(auto a:nums)
{
ret^=a;
}
return ret;
}
};
3.2 杨辉三角
题目链接:
题目描述:

题目示例:

C++算法代码:
cpp
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> vv;
//行
vv.resize(numRows,vector<int>());
//列
for(size_t n=0;n<numRows;n++)
{
vv[n].resize(n+1,1);
}
for(size_t i=2;i<vv.size();i++)//从第三行开始
{
for(size_t j=1;j<vv[i].size()-1;j++)//从第二列到倒数第二列
{
vv[i][j]=vv[i-1][j]+vv[i-1][j-1];
}
}
return vv;
}
};
结尾:
往期回顾:
C++ string 类使用超全攻略:从入门到高效避坑,日常开发直接使用_c语言怎么使用string输入字符串-CSDN博客
《告别 "会用不会讲":C++ string 底层原理拆解 + 手撕实现,面试 / 开发都适用》-CSDN博客
结语:掌握这些核心知识点,vector 就能成为你开发和刷题中的 "万能工具",既高效又可靠。
建议结合实际代码练习,尤其是迭代器失效和二维 vector 的使用,彻底吃透这个 STL 核心容器。
✨把这些内容吃透超牛的!放松下吧✨
ʕ˘ᴥ˘ʔ
づきらど