C中的vector是什么意思?
摘要:深入理解 C++ 中最常用的容器 std::vector:动态数组的核心特性、内存管理、扩容机制、迭代器失效问题,以及 reserve、emplace_back 等现代化最佳实践。特别提醒 std::ve
目录核心特性与底层原理初始化与构造容量与大小为什么 reserve 非常重要?增删查改插入与添加删除访问迭代器失效特殊版本:std::vector<bool>现代化操作C++20:std::erase 和 std::erase_if最佳实践
本文首发于我的个人博客:Better Mistakes
版权声明:本文为原创文章,转载请附上原文出处链接及本声明。
由于技术迭代较快,文章内容可能随时更新(含勘误及补充)。为了确保您看到的是最新版本,并获得更好的代码阅读体验,请访问:
🍭 原文链接:https://bfmhno3.github.io/note/vector-in-cpp/
std::vector 是 C++ 中最重要、最常用的容器,没有之一。它的本质是动态数组(Dynamic Array)。
std::vector 是在堆(Heap)上管理一块连续的内存,可以存放任意类型的对象。
核心特性与底层原理
头文件:#include <vector>
内存模型:连续内存。这意味着它和 C 数组一样,支持通过指针偏移量快速访问,并且对 CPU 缓存(Cache)非常友好。
自动扩容:当存入数据量超过当前容量时,std::vector 就会申请一块更大的内存(通常是原来的 1.5 倍或 2 倍),将旧数据移动/拷贝过去,然后释放旧内存。
初始化与构造
#include <vector>
// 1. 默认构造(空 vector)
std::vector<int> v1;
// 2. 指定大小和默认值
std::vector<int> v2(10); // 10 个元素,默认初始化 0
std::vector<int> v3(10, 5); // 10 个元素,每个都是 5
// 3. 列表初始化(C++11)
std::vector<int> v4 = {1, 2, 3, 4};
// 4. 拷贝构造
std::vector<int> v5(v4);
// 5. 迭代器范围构造(常用与从其他容器拷贝)
int arr[] = {10, 20, 30}
std::vector<int> v6(arr, arr + 3);
容量与大小
函数
说明
备注
size()
当前元素个数
实际存了多少个
capacity()
当前分配的内存能存多少个
capacity \(\geqslant\) size
empty()
是否为空
推荐使用,比 size() == 0 更语义化
reserve()
预分配内存
仅改变 capacity,不改变 size
resize(n)
改变元素个数
改变 size,如果变大则填充默认值
shrink_to_fit()
释放未使用的内存(C++11)
让 capacity 搜索到 size 大小
为什么 reserve 非常重要?
std::vector<int> v;
v.reserve(1000); // 一次性分配好内存
for (int i = 0; i < 1000; i++) {
v.push_back(i); // 这里不会再发生内存重新分配,效率极高
}
增删查改
插入与添加
push_back(val):在尾部添加元素(会发生拷贝或移动)。
emplace_back(arg...)(C++11):原地构造。直接在 std::vector 尾部构造对象,省去了一次临时对象的构造和拷贝 / 移动,效率通常更高。
insert(it, val):在迭代器指向的位置插入。效率为 \(O(N)\),因为要移动后续所有元素。
删除
pop_back:删除尾部元素(\(O(1)\))。
erase(it):删除指定位置元素(\(O(N)\),后续元素前移)。
clear():清空所有元素,szie 变为 0,但 capacity 通常不变(内存不释放)。
访问
v[i]:下标访问,不检查越界。
v.at[i]:检查越界,越觉抛 std::out_of_range。
v.front() / v.back():访问首尾。
v.data():返回指向底层数组首元素的指针(T*)。常用于和 C 语言 API 交互。
迭代器失效
由于 std::vector 是连续内存,当结构发生变化时,指向旧内存的迭代器、指针、引用可能会失效。
