前言
vector 是 C++ STL 中最常用的动态数组容器,支持动态扩容、随机访问,且接口丰富,是日常开发和学习中的高频工具。本文基于个人练习代码整理,修改了原有的简单函数名(如 test14
改为 vector_declare_and_init
),并添加详细注释和知识点总结,方便后续复习时快速理解核心用法。
一、向量基础:声明与初始化(原 test14、test15)
1.1 功能说明
掌握 vector 不同场景下的初始化方式,包括直接赋值、指定大小和默认值、拷贝初始化等,覆盖日常开发中 90% 的初始化需求。
1.2 代码实现(含详细注释)
cpp
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <math.h>
#include <ctime>
using namespace std;
// -------------------------- 向量声明与初始化 --------------------------
// 功能:演示vector的基础声明与初始化(直接赋值初始化)
void vector_declare_and_init_basic() {
// 1. 初始化int类型vector,直接赋值元素
vector<int> vec_int = { 1, 2, 3, 4 };
// 2. 初始化char类型vector,存储字符串"hello"的每个字符
vector<char> vec_char = { 'h', 'e', 'l', 'l', 'o' };
// 3. 初始化string类型vector,存储多个字符串
vector<string> vec_str = { "hello", "abc", "world" };
// 访问vector元素:通过下标[]访问(无越界检查,需确保下标合法)
cout << "vec_int第1个元素(下标0):" << vec_int[0] << endl; // 输出1
cout << "vec_str第1个字符串(下标0):" << vec_str[0] << endl; // 输出hello
}
// 功能:演示vector的进阶初始化(指定大小、拷贝、范围初始化)
void vector_declare_and_init_advance() {
// 1. 初始化int类型vector,指定大小为10,默认值为0(未显式指定默认值时,基础类型默认初始化)
vector<int> vec_size10(10);
cout << "vec_size10第1个元素(默认值):" << vec_size10[0] << endl; // 输出0
// 2. 初始化int类型vector,指定大小为10,所有元素默认值为6
vector<int> vec_size10_val6(10, 6);
cout << "vec_size10_val6第1个元素(指定默认值6):" << vec_size10_val6[0] << endl; // 输出6
// 3. 拷贝初始化:将vec_size10_val6的所有元素拷贝到vec_copy
vector<int> vec_copy(vec_size10_val6);
cout << "vec_copy第2个元素(拷贝自vec_size10_val6):" << vec_copy[1] << endl; // 输出6
// 4. 范围初始化:将vec_size10_val6的[begin, begin+1)区间元素拷贝到vec_range(左闭右开,仅拷贝第1个元素)
// 注意:vector的迭代器是随机访问迭代器,支持+/-运算
vector<int> vec_range(vec_size10_val6.begin(), vec_size10_val6.begin() + 1);
cout << "vec_range的元素个数(size):" << vec_range.size() << endl; // 输出1(仅拷贝1个元素)
cout << "vec_range第1个元素:" << vec_range[0] << endl; // 输出6
}
1.3 知识点总结
初始化方式 | 语法示例 | 适用场景 |
---|---|---|
直接赋值初始化 | vector<int> vec = {1,2,3} |
已知具体元素,直接初始化 |
指定大小(默认值) | vector<int> vec(10, 6) |
需要固定大小、统一默认值的场景(如初始化数组) |
拷贝初始化 | vector<int> vec(src_vec) |
基于已有 vector 创建副本 |
范围初始化(左闭右开) | vector<int> vec(src.begin(), src.end()) |
仅需要已有 vector 的部分元素 |
二、向量元素访问:at ()、front ()、back () 与迭代器遍历(原 test16)
2.1 功能说明
掌握 vector 元素的多种访问方式,包括安全访问(at()
)、首尾元素快速访问(front()
/back()
),以及正向 / 反向迭代器遍历,覆盖不同场景下的元素读取需求。
2.2 代码实现(含详细注释)
cpp
// -------------------------- 向量元素访问与遍历 --------------------------
void vector_access_and_traverse() {
// 初始化一个int类型vector,元素为1~6
vector<int> vec = { 1, 2, 3, 4, 5, 6 };
// 1. 安全访问:at()方法(会做越界检查,越界时抛出out_of_range异常)
cout << "vec下标3的元素(at()访问):" << vec.at(3) << endl; // 输出4(下标3对应第4个元素)
// 2. 快速访问首尾元素:front()(首元素)、back()(尾元素)
cout << "vec首元素(front()):" << vec.front() << endl; // 输出1
cout << "vec尾元素(back()):" << vec.back() << endl; // 输出6
// 3. 正向迭代器遍历:从begin()(首元素)到end()(尾元素的下一个位置,不可访问)
cout << "正向遍历(迭代器):";
for (auto it = vec.begin(); it != vec.end(); ++it) { // auto自动推导迭代器类型(vector<int>::iterator)
cout << *it << "\t"; // 迭代器解引用获取元素值,输出:1 2 3 4 5 6
}
cout << endl;
// 4. 反向迭代器遍历:从rbegin()(尾元素)到rend()(首元素的前一个位置,不可访问)
cout << "反向遍历(迭代器):";
for (auto it = vec.rbegin(); it != vec.rend(); ++it) { // 反向迭代器:++it表示向前移动
cout << *it << "\t"; // 输出:6 5 4 3 2 1
}
cout << endl;
}
2.3 知识点总结
- 访问方式对比 :
[]
:无越界检查,效率高,适合确定下标合法的场景;at()
:有越界检查,安全,越界抛异常,适合不确定下标合法性的场景;front()
/back()
:直接访问首尾元素,无需下标,效率最高。
- 迭代器遍历 :
- 正向迭代器:
begin()
→end()
,++it
向后移动; - 反向迭代器:
rbegin()
→rend()
,++it
向前移动(注意:反向迭代器的++
是 "反向前进"); auto
关键字可简化迭代器类型声明(C++11 及以后支持)。
- 正向迭代器:
三、向量元素添加:push_back () 与 insert ()(原 test17)
3.1 功能说明
掌握 vector 元素的添加方法,包括尾部添加(push_back()
)和指定位置插入(insert()
),理解不同添加方式的适用场景和性能差异。
3.2 代码实现(含详细注释)
cpp
// -------------------------- 向量元素添加 --------------------------
void vector_add_elements() {
// 初始vector:int类型,元素为1、2
vector<int> vec = { 1, 2 };
// 辅助vector:int类型,元素为100、200(用于范围插入)
vector<int> vec_aux = { 100, 200 };
// 1. 尾部添加:push_back()(在vector末尾追加元素,效率高,仅需偶尔扩容)
vec.push_back(3); // vec变为:{1, 2, 3}
// 2. 指定位置插入:insert(位置迭代器, 元素值)(在迭代器指向的位置前插入元素)
vec.insert(vec.begin(), 66); // 在首元素(1)前插入66,vec变为:{66, 1, 2, 3}
// 3. 批量插入:insert(位置迭代器, 数量, 元素值)(在指定位置前插入n个相同元素)
// 位置:vec.begin()+1(即1的前一个位置),插入10个99
vec.insert(vec.begin() + 1, 10, 99); // vec变为:{66, 99(10个), 1, 2, 3}
// 4. 范围插入:insert(位置迭代器, 源.begin(), 源.end())(插入另一个容器的指定范围元素)
// 位置:vec.begin()(首元素前),插入vec_aux的所有元素(100、200)
vec.insert(vec.begin(), vec_aux.begin(), vec_aux.end()); // vec最终:{100, 200, 66, 99(10个), 1, 2, 3}
// 遍历输出所有元素,验证插入结果
cout << "插入后所有元素:";
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
3.3 知识点总结
push_back()
:- 优势:尾部添加,无需移动元素,仅当容量不足时扩容,效率最高;
- 适用场景:只需在末尾添加元素的场景(如收集数据)。
insert()
:- 优势:支持任意位置插入(头部、中间、尾部),灵活;
- 劣势:插入位置非尾部时,需移动后续元素,元素越多效率越低;
- 常用形式:
- 单个元素:
insert(it, val)
; - 批量元素:
insert(it, n, val)
; - 范围元素:
insert(it, src.begin(), src.end())
。
- 单个元素:
四、向量元素删除:erase ()、pop_back () 与 clear ()(原 test18)
4.1 功能说明
掌握 vector 元素的删除方法,包括指定位置删除(erase()
)、尾部删除(pop_back()
)和清空所有元素(clear()
),注意删除后迭代器失效问题。
4.2 代码实现(含详细注释)
cpp
// -------------------------- 向量元素删除 --------------------------
void vector_remove_elements() {
// 初始vector:int类型,元素为1~6
vector<int> vec = { 1, 2, 3, 4, 5, 6 };
// 1. 判断vector是否为空:empty()(返回bool,true为空,false非空)
cout << "删除前vector是否为空(0=非空,1=空):" << vec.empty() << endl; // 输出0(非空)
// 2. 指定位置删除单个元素:erase(位置迭代器)(删除迭代器指向的元素)
vec.erase(vec.begin() + 1); // 删除下标1的元素(2),vec变为:{1, 3, 4, 5, 6}
// 3. 指定范围删除元素:erase(起始迭代器, 结束迭代器)(左闭右开,删除[it1, it2)区间元素)
vec.erase(vec.begin() + 2, vec.begin() + 4); // 删除下标2~3的元素(4、5),vec变为:{1, 3, 6}
// 4. 尾部删除:pop_back()(删除末尾元素,效率高,无需移动其他元素)
vec.pop_back(); // 删除尾元素(6),vec变为:{1, 3}
// 5. 清空所有元素:clear()(删除所有元素,size变为0,但capacity不变)
vec.clear(); // vec变为空(size=0),但容量(capacity)仍为初始分配的大小
// 再次判断vector是否为空
cout << "删除后vector是否为空(0=非空,1=空):" << vec.empty() << endl; // 输出1(空)
// 遍历输出(此时vector为空,无元素输出)
cout << "清空后遍历:";
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
4.3 知识点总结
- 删除方法对比 :
pop_back()
:尾部删除,效率高,无迭代器失效问题(仅尾元素删除);erase(it)
:删除单个元素,删除后it
及后续迭代器失效,需重新获取迭代器;erase(it1, it2)
:删除范围元素,删除后it1
及后续迭代器失效;clear()
:清空所有元素,size()
变为 0,但capacity()
不变(内存未释放,可复用)。
- 迭代器失效注意 :
- 删除非尾部元素后,后续元素会前移,原迭代器指向的位置可能变为无效元素;
- 解决方法:删除后通过
erase()
的返回值获取新迭代器(如it = vec.erase(it)
)。
五、向量容量操作:size ()、capacity ()、max_size () 与 empty ()(原 test19)
5.1 功能说明
理解 vector 的 "大小"(size()
)和 "容量"(capacity()
)的区别,掌握容量相关操作,避免因频繁扩容导致性能损耗。
5.2 代码实现(含详细注释)
cpp
// -------------------------- 向量容量操作 --------------------------
void vector_capacity_operations() {
// 初始vector:int类型,元素为1~6
vector<int> vec = { 1, 2, 3, 4, 5, 6 };
// 1. size():返回vector当前存储的元素个数(实际元素数量)
cout << "初始size(元素个数):" << vec.size() << endl; // 输出6
// 2. capacity():返回vector当前已分配的内存可容纳的元素个数(容量≥size,扩容时会增加)
cout << "初始capacity(容量):" << vec.capacity() << endl; // 输出6(初始分配的容量刚好容纳6个元素)
// 3. max_size():返回vector理论上可容纳的最大元素个数(受系统内存限制,通常很大)
cout << "max_size(最大可容纳元素数):" << vec.max_size() << endl; // 输出一个大整数(如2^31-1,取决于系统)
// 4. 尾部删除元素:pop_back()(仅减少size,不改变capacity)
vec.pop_back(); // 删除尾元素(6),size变为5,capacity仍为6
// 再次查看size和capacity
cout << "pop_back后size:" << vec.size() << endl; // 输出5
cout << "pop_back后capacity:" << vec.capacity() << endl; // 输出6(容量未变,内存未释放)
cout << "pop_back后max_size:" << vec.max_size() << endl; // 输出不变(不受删除影响)
}
5.3 知识点总结
- 核心概念区分 :
size()
:实际元素个数("当前有多少个苹果");capacity()
:已分配内存可容纳的最大元素个数("篮子能装多少个苹果");max_size()
:理论最大容量("仓库最多能放多少个篮子")。
- 扩容机制 :
- 当
size() == capacity()
时,再添加元素会触发扩容(通常扩容为原容量的 1.5~2 倍); - 扩容会分配新内存、拷贝旧元素、释放旧内存,频繁扩容会影响性能,可提前用
reserve(n)
预分配容量。
- 当
六、向量赋值与交换:assign () 与 swap ()(原 test20)
6.1 功能说明
掌握 vector 的赋值(assign()
)和交换(swap()
)操作,理解 assign()
与直接赋值(=
)的区别,以及 swap()
的高效性。
6.2 代码实现(含详细注释)
cpp
// -------------------------- 向量赋值与交换 --------------------------
void vector_assign_and_swap() {
// 1. assign():重新赋值(覆盖原有元素,size和capacity可能改变)
vector<int> vec_assign;
// assign(数量, 值):将vec_assign赋值为10个22(覆盖原有元素,原有元素会被销毁)
vec_assign.assign(10, 22);
cout << "assign(10,22)后元素:";
for (auto it = vec_assign.begin(); it != vec_assign.end(); ++it) {
cout << *it << " "; // 输出10个22:22 22 22 ... 22
}
cout << endl;
// 2. swap():交换两个vector的内容(仅交换内部指针,效率极高,无元素拷贝)
vector<int> vec_swap1 = { 1, 2, 3, 4 }; // 初始vec_swap1:{1,2,3,4}
vector<int> vec_swap2 = { 100, 200, 300, 400, 500, 600 }; // 初始vec_swap2:{100,200,...600}
cout << "swap前vec_swap1:";
for (auto it = vec_swap1.begin(); it != vec_swap1.end(); ++it) {
cout << *it << " "; // 输出:1 2 3 4
}
cout << endl;
cout << "swap前vec_swap2:";
for (auto it = vec_swap2.begin(); it != vec_swap2.end(); ++it) {
cout << *it << " "; // 输出:100 200 300 400 500 600
}
cout << endl;
// 交换vec_swap1和vec_swap2的内容
vec_swap1.swap(vec_swap2);
cout << "swap后vec_swap1:";
for (auto it = vec_swap1.begin(); it != vec_swap1.end(); ++it) {
cout << *it << " "; // 输出原vec_swap2的内容:100 200 300 400 500 600
}
cout << endl;
cout << "swap后vec_swap2:";
for (auto it = vec_swap2.begin(); it != vec_swap2.end(); ++it) {
cout << *it << " "; // 输出原vec_swap1的内容:1 2 3 4
}
cout << endl;
}
6.3 知识点总结
assign()
与直接赋值(=
)的区别 :assign(n, val)
:可指定 "数量 + 值" 赋值,适合重新初始化;assign(src.begin(), src.end())
:可赋值另一个容器的范围元素;- 直接赋值(
vec1 = vec2
):仅能拷贝整个容器的元素,功能不如assign()
灵活。
swap()
的优势 :- 高效:仅交换两个 vector 的内部指针(指向数据的指针、size、capacity),无元素拷贝;
- 用途:快速交换两个 vector 的内容,或用于释放 vector 的内存(如
vector<int>().swap(vec)
清空并释放内存)。
七、向量实战案例:生成随机数并查找最值(原 test21)
7.1 功能说明
结合 vector 的初始化、元素添加、遍历操作,实现 "输入 n,生成 n 个 1~100 的随机数,存入 vector 并查找最值" 的实战需求,巩固 vector 的综合用法。
7.2 代码实现(含详细注释)
cpp
// -------------------------- 向量实战:随机数生成与最值查找 --------------------------
void vector_practice_random_max_min() {
// 1. 输入需要生成的随机数个数n
int n;
cout << "请输入需要生成的随机数个数n:";
cin >> n;
// 2. 初始化vector,用于存储随机数
vector<int> vec_random;
// 3. 初始化随机数种子:确保每次运行生成的随机数不同(依赖系统时间)
// time(0)返回当前系统时间(秒级),srand()设置随机数种子
srand(time(0));
// 4. 生成n个1~100的随机数,存入vector
cout << "生成的" << n << "个随机数:";
for (int i = 0; i < n; i++) {
// rand()生成0~RAND_MAX的随机数,%100后范围为0~99,+1后变为1~100
int num = (rand() % 100) + 1;
vec_random.push_back(num); // 尾部添加随机数到vector
cout << num << " "; // 实时输出随机数,方便验证
}
cout << endl;
// 5. 查找vector中的最大值和最小值
// 初始化max和min为vector的第一个元素(需确保vector非空,此处n≥1)
int max_val = vec_random.at(0); // 用at()安全访问,避免越界
int min_val = vec_random[0]; // 用[]访问,效率高
// 遍历vector,更新max和min
for (int i = 0; i < vec_random.size(); i++) {
// 若当前元素大于max_val,更新max_val
if (max_val < vec_random[i]) {
max_val = vec_random[i];
}
// 若当前元素小于min_val,更新min_val
if (min_val > vec_random[i]) {
min_val = vec_random[i];
}
}
// 6. 输出结果
cout << "随机数中的最大值max:" << max_val << endl;
cout << "随机数中的最小值min:" << min_val << endl;
}
7.3 知识点总结
- 随机数生成要点 :
- 必须用
srand(time(0))
初始化种子,否则每次运行生成的随机数序列相同; rand()%100 + 1
是常用的 "范围缩放" 技巧,将随机数从[0, RAND_MAX]
缩放到[1, 100]
。
- 必须用
- 最值查找逻辑 :
- 初始值必须从 vector 中取(不能用固定值如 0,避免随机数全大于 0 导致 min 错误);
- 一次遍历同时更新 max 和 min,效率更高(仅遍历一次,时间复杂度 O (n))。
八、vector 核心特性与常用操作总结
8.1 核心特性
- 动态扩容:支持自动扩容,容量不足时自动分配更大内存(通常为原容量的 1.5~2 倍);
- 随机访问 :支持
[]
和at()
访问,访问任意元素的时间复杂度 O (1); - 连续内存:元素存储在连续内存中,缓存友好,但插入 / 删除中间元素效率低(需移动元素);
- 无内置排序 :需用
<algorithm>
头文件的sort(vec.begin(), vec.end())
排序(vector 支持随机访问迭代器,可排序)。
8.2 常用操作速查表
操作类别 | 函数名 | 功能描述 |
---|---|---|
初始化 | vector<T> vec |
空 vector |
vector<T> vec(n, val) |
大小 n,默认值 val | |
元素访问 | vec[i] |
下标访问(无越界检查) |
vec.at(i) |
安全访问(越界抛异常) | |
vec.front() /vec.back() |
访问首尾元素 | |
元素添加 | vec.push_back(val) |
尾部添加元素 |
vec.insert(it, val) |
指定位置插入元素 | |
元素删除 | vec.pop_back() |
尾部删除元素 |
vec.erase(it) |
指定位置删除元素 | |
vec.clear() |
清空所有元素(size=0,capacity 不变) | |
容量操作 | vec.size() |
元素个数 |
vec.capacity() |
容量(可容纳元素个数) | |
vec.empty() |
判断是否为空 | |
赋值与交换 | vec.assign(n, val) |
重新赋值为 n 个 val |
vec1.swap(vec2) |
交换两个 vector 的内容 |
结语
vector 是 C++ STL 中最基础也最常用的容器,掌握其初始化、访问、增删改查、容量操作和实战用法,能应对大部分日常开发需求。本文通过修改函数名、添加详细注释和知识点总结,将零散的练习代码整理为体系化的学习笔记,后续复习时可根据模块快速定位所需知识点,也可直接复用代码中的实战逻辑(如随机数生成、最值查找)。
最后附上我自己练习时的源码资料(有兴趣的可以按自己喜好自由练习修改):
头文件:
cpp
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <math.h>
#include <ctime>
using namespace std;
/*
声明函数方法
*/
void test14();
void test15();
void test16();
void test17();
void test18();
void test19();
void test20();
/*
案例题目
输入n,随机n个1~100的数字,装入vector,找出里面最大值和最小值
*/
void test21();
源文件:
cpp
#include "vector容器.h"
/*
函数方法定义实现
*/
/*
案例题目
输入n,随机n个1~100的数字,装入vector,找出里面最大值和最小值
*/
void test21() {
//输入n
int n;
cin >> n;
//随机n个1~100的数字 //装入vector
vector<int> v;
//srand((unsigned)time(NULL));
srand(time(0));
//srand(time(NULL));
for (int i = 0; i < n; i++) {
int num = (rand() % 100)+1;//[0,100)=>[1,101)=>[1,100]
v.push_back(num);
}
//找出里面最大值和最小值
int max = v.at(0);
int min = v[0];
for (int i = 0; i < v.size(); i++) {
if (max < v[i]) {
max = v[i];
}
if (min > v[i]) {
min = v[i];
}
}
for (auto i = v.begin(); i != v.end(); i++) {
cout << *i << " ";
}
cout << endl;
cout << "max=" << max << endl;
cout << "min=" << min << endl;
}
void test20() {
vector<int> v;
v.assign(10, 22); //把v里面前10个元素设置成22
//cout << v.size();
for (auto i = v.begin(); i != v.end(); i++) {
cout << *i << " ";
}
cout << endl;
vector<int> v1 = { 1,2,3,4 };
vector<int> v2 = { 100,200,300,400,500,600 };
//使用v1的元素替换掉v2的元素
//v2.assign(v1.begin(), v1.end());
v1.swap(v2); //v1和v2的值进行交换
for (auto i = v1.begin(); i != v1.end(); i++) {
cout << *i << " ";
}
cout << endl;
for (auto i = v2.begin(); i != v2.end(); i++) {
cout << *i << " ";
}
cout << endl;
}
void test19() {
vector<int> v = { 1,2,3,4,5,6 };
cout << "v.size=" << v.size() << endl;
cout << "v.capacity=" << v.capacity() << endl;
cout << "v.max_size=" << v.max_size() << endl;
v.pop_back();
cout << "v.size=" << v.size() << endl;
cout << "v.capacity=" << v.capacity() << endl;
cout << "v.max_size=" << v.max_size() << endl;
}
void test18() {
vector<int> v = { 1,2,3,4,5,6 };
cout << v.empty() << endl;
v.erase(v.begin() + 1);//删除2
//v.insert(v.begin() + 1, 2);
v.erase(v.begin() + 2, v.begin() + 4);//删除4,5
v.pop_back(); //删除最后一个6
v.clear(); //删除所有元素
cout << v.empty() << endl;
for (auto i = v.begin(); i != v.end(); i++) {
cout << *i << " ";
}
cout << endl;
}
void test17() {
vector<int> v = { 1,2 };
vector<int> v2 = { 100,200 };
v.push_back(3); //在2的后面添加3
v.insert(v.begin(), 66); //在1的前面插入66
v.insert(v.begin() + 1, 10, 99); //在1和66之间插入10个99
v.insert(v.begin(), v2.begin(), v2.end()); //把v2的所有元素插入到v的头部
for (auto i = v.begin(); i != v.end(); i++) {
cout << *i << " ";
}
cout << endl;
}
void test16() {
vector<int> v = { 1,2,3,4,5,6 };
cout << v.at(3) << endl; //取下标为3的元素4
cout << v.front() << endl; //输出首元素
cout << v.back() << endl; //输出尾元素
//循环迭代打印所有元素
for (auto i = v.begin(); i != v.end(); i++) {
cout << *i << "\t";
}
cout << endl;
//反向打印所有元素
for (auto i = v.rbegin(); i != v.rend(); i++) {
cout << *i << "\t";
}
cout << endl;
}
void test15() {
vector<int> v1(10); //定义一个含有10个变量的整型向量,默认值是0
cout << v1[0] << endl;
vector<int> v2(10, 6); //定义一个含有10个变量的整型向量,默认值是6
cout << v2[0] << endl;
vector<int> v3(v2); //把v2拷贝给v3
cout << v3[1] << endl;
vector<int> v4(v2.begin(), v2.begin() + 1); //把v2的[v2.begin(),v2.begin()+1)值拷贝给v4
cout << v4.size() << endl;
cout << v4[0] << endl;
}
//vector声明和初始化
void test14() {
vector<int> v1 = { 1,2,3,4 };
vector<char> v2 = { 'h','e','l','l','o' };
vector<string> v3 = { "hello","abc" ,"world"};
cout << v1[0] << endl;
cout << v3[0] << endl;
}