vector的size()表示实际元素个数,capacity()表示已分配但未使用的内存空间;因采用连续内存与预留策略(如2倍扩容),二者常不等,以减少频繁重分配。

vector 增删元素时,为什么 size() 和 capacity() 不一样?
因为 vector 在内存里是连续分配的,但不会每次 push_back() 都重新 malloc —— 它会预留额外空间(capacity()),避免频繁重分配。实际元素个数才是 size()。
- 新增用
push_back()(尾插)或insert()(任意位置),前者均摊 O(1),后者最坏 O(n) - 删除优先用
pop_back()(O(1)),别用erase()删除中间元素——它要搬移后续所有元素 - 如果明确知道后续要插入大量元素,先调
reserve(n),否则可能触发多次扩容(2倍增长,有拷贝开销) -
clear()只清逻辑内容,不释放内存;真要缩容得写vector<int>(v).swap(v)</int>
用 vector 查找元素,别手写 for 循环
标准库早提供了 std::find 和 std::find_if,语义清晰、编译器还能做优化,自己遍历容易越界或漏 const 限定。
- 查值:用
std::find(v.begin(), v.end(), target) != v.end() - 查满足条件的元素:用
std::find_if(v.begin(), v.end(), [](int x){ return x > 10; }) - 注意:返回的是迭代器,不是下标;要转下标用
it - v.begin(),但得先判是否有效 - 如果 vector 已排序,直接上
std::lower_bound或std::binary_search,O(log n)
vector 初始化和赋值,这些写法效果完全不同
初始化方式决定内存行为和构造时机,尤其涉及自定义类型时,错一个符号就多调几次构造/析构函数。
-
vector<int> v(10);</int>→ 创建含 10 个 0 的 vector(调 default 构造) -
vector<int> v{1, 2, 3};</int>→ 初始化列表,元素直接构造,无拷贝 -
vector<int> v = {1, 2, 3};</int>→ 同上,但 C++17 起 guaranteed copy elision,安全 -
v.assign({1, 2, 3});→ 运行时替换内容,旧元素先析构 -
v = {1, 2, 3};→ 赋值操作,等价于 assign,但更简洁
迭代器失效:哪些操作会让 it 变成野指针?
vector 的内存是连续的,只要发生扩容或删除中间元素,原有迭代器大概率失效——这不是 bug,是标准明确定义的行为。
立即学习“C++免费学习笔记(深入)”;
- 以下操作一定使所有迭代器失效:
push_back()(触发扩容时)、insert()(任何位置)、erase()(任何位置)、clear()、resize()(变大且需扩容时) - 只有
pop_back()和resize()(变小)不影响其他迭代器有效性 - 循环中边遍历边删?别用普通 for +
erase(),改用remove-erase idiom:v.erase(remove_if(v.begin(), v.end(), pred), v.end()) - 调试时加
-D_GLIBCXX_DEBUG(GCC)能捕获大部分迭代器误用
用 vector 本身不难,难在它把内存管理藏得太深——你看到的是“动态数组”,背后却是连续内存 + 指针算术 + 迭代器模型 + 移动语义的组合。稍不注意,capacity()、迭代器、移动构造这几个点就会在运行时咬你一口。










