std::vector::push_back()是最直接的末尾追加方案,自动管理内存、检查容量并复制元素;误用operator[]越界、忽略reserve()性能优化、手动new[]替代vector、混淆emplace_back()适用场景及忽视值语义影响是常见错误。

std::vector::push_back() 是最直接的方案
动态数组在 C++ 里通常指 std::vector,它内部自动管理堆内存,push_back() 就是专为末尾追加设计的成员函数。调用时会检查容量,不够就重新分配并复制元素——你不用手动算 size、realloc 或 memcpy。
常见错误是误用 operator[] 赋值越界:v[v.size()] = x 行为未定义,因为 v.size() 已超出合法下标范围(合法是 [0, v.size()))。
示例:
std::vector<int> v = {1, 2};
v.push_back(3); // 正确:v 变为 {1, 2, 3}
// v[3] = 4; // 错误:访问越界
</int>
reserve() 和 capacity() 影响性能但不改变逻辑
频繁调用 push_back() 可能触发多次内存重分配,导致 O(n) 摊还时间。如果预估最终大小,提前 reserve() 能避免中间复制。
注意:reserve() 只影响 capacity(),不改变 size(),也不构造元素;resize() 才会真正增加 size 并默认初始化新元素。
-
v.reserve(100):确保至少能存 100 个元素,后续最多 100 次push_back()不会 realloc -
v.resize(100):立刻让v.size() == 100,新增位置用默认值(如 0)填充 - 调用
push_back()后,v.size()增 1,v.capacity()可能不变、也可能翻倍增长(实现相关)
原始指针 + new[] 的手动方式极不推荐
有人试图用 int* arr = new int[n] 模拟动态数组,再每次 new int[n+1] 复制旧数据——这不仅容易内存泄漏,还违背 RAII 原则,且无法自动析构对象(比如 std::string 成员)。
若必须用裸指针(如嵌入式或特殊 ABI 约束),至少封装成类并严格配对 delete[];但日常开发中,std::vector 是唯一合理选择。
典型坑:
- 忘记
delete[] old_ptr→ 内存泄漏 - 复制时漏掉某个对象的拷贝构造 → 析构时 double-free 或未定义行为
- 用
sizeof(arr)当长度 → 实际得到指针大小(通常是 8)
emplace_back() 适合含参构造的对象
当添加的是自定义类型(如 std::string("hello") 或 MyClass(1, "test")),emplace_back() 可直接在 vector 末尾原地构造,避免临时对象和移动/拷贝开销。
对于 int、double 这类 trivial 类型,push_back() 和 emplace_back() 效果一致;但写法上 emplace_back(42) 比 push_back(int{42}) 更直观。
注意:传参必须匹配目标类型的构造函数签名,否则编译失败,而非静默降级。
真正麻烦的不是“怎么加”,而是忘了 vector 是值语义——传参时默认拷贝整块数据,迭代器可能失效,多线程下需额外同步。这些细节比追加本身更常引发问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











