append 不比 + 和 += 慢;它零拷贝追加(容量足够时),远优于需复制全部内容的 operator+;+= 与 append 行为几乎一致,语义更清晰,编译后汇编通常无差别;隐式扩容(size==capacity)使 append 退化为 O(n);预分配用 reserve(),不改变 size 且开销极小;循环前 reserve 可避免多次扩容;resize() 不适用,因会初始化内存并改变 size;预留比预估多 10%~20% 容量常获 2–5 倍性能提升。

append 比 + 和 += 慢吗?
不慢,append 本身是零拷贝追加(只要容量够),比 operator+ 高效得多——后者每次都会构造新对象并复制全部内容。+= 行为和 append 几乎一致,但语义上更易读;实际编译后汇编通常没差别。真正拖慢的是隐式扩容:当 size() == capacity() 时,append 必须重新分配内存、复制旧数据,复杂度从 O(1) 退化为 O(n)。
怎么预分配避免多次扩容?
在已知最终长度或有合理上界时,调用 reserve() 显式预留空间。它只改变 capacity(),不改变 size(),也不初始化内存,开销极小。
- 如果拼接前能估算总长(比如 10 个字符串各约 20 字节),直接
s.reserve(256) - 若分多轮拼接(如循环中不断
append),务必在循环前reserve,别在循环内反复调用 - 注意:
resize()不是替代方案——它会填充字符并改变size(),后续append仍可能触发扩容
reserve 多大才合适?
没有银弹,但有两个关键事实:
- STL 实现(如 libstdc++、libc++)通常按 1.5× 或 2× 增长容量,频繁小增量扩容代价很高
- 过度预留(如 reserve(1MB) 只用 1KB)浪费内存,但对现代系统影响常小于反复 malloc/free 的延迟和碎片
- 实测表明:预留比预估多 10%~20% 容量,往往比精确计算或不预留快 2–5 倍(尤其在千次以上拼接场景)
例如:string s; s.reserve(1000); for (int i = 0; i —— 这比无 reserve 快一个数量级。
立即学习“C++免费学习笔记(深入)”;
哪些情况 reserve 无效或反效果?
reserve 对空字符串或已足够大的容量无害,但以下场景需谨慎:
- 拼接总量完全不可预估(如解析网络流中的不定长 JSON 字段),强行 reserve 可能分配过大内存或频繁重估
- 字符串生命周期极短(如函数局部临时量),且拼接次数少于 3 次,优化收益几乎为零
- 使用
std::string_view或写时复制(COW)实现的旧库(如某些嵌入式 STL),reserve可能触发不必要的深拷贝
真正容易被忽略的是:reserve 不会释放已有内存,即使你随后 clear(),capacity() 仍保持高位——这在长生命周期对象中可能导致“内存只增不减”。需要收缩时,得用 string().swap(s) 或 C++11 后的 s.shrink_to_fit()(但后者是提示,不保证执行)。










