append用于在字符串末尾追加内容,支持多种重载;常见误用是未调用reserve就循环append,引发多次内存重分配。
append 是 std::string 的成员函数,用于在字符串末尾追加内容,比 operator+= 更灵活,支持多种重载形式:追加子串、C 风格字符串、字符、重复字符、迭代器区间等。
常见错误是反复调用 append 而不预留空间,导致多次内存重分配:
std::string s;
for (int i = 0; i < 1000; ++i) {
s.append(std::to_string(i)); // 每次都可能 realloc
}reserve()
append(1, c) 替代 push_back(c):后者更轻量,无长度检查开销append(str) 和 append(str.c_str()) 行为不同:前者走 const std::string& 重载(可能短字符串优化),后者走 const char* 重载(需 strlen 扫描)现代 libstdc++ 和 libc++ 的 std::string 多数采用 SSO(短字符串优化),但一旦超出 SSO 容量(通常 15–22 字节),后续 append 就触发堆分配。频繁扩容的代价远高于一次预分配。
实测显示:对最终长度约 10KB 的拼接任务,reserve(10240) 可使总耗时下降 40%~70%,取决于编译器和 STL 实现。
append 前调用 reserve()
reserve(256),每次接近容量时 reserve(size() * 2)
reserve(n) 不改变 size(),只影响 capacity();调用后仍需用 append 或 += 写入数据三者语义和性能边界清晰:append 和 += 都只支持尾部追加,而 insert 支持任意位置插入(代价更高)。实际中 95% 的拼接应使用前两者之一。
+= 最简洁:适合单个字符串、字符或字面量,编译器通常能内联优化append 当你需要控制追加范围:比如 s.append(other, 2, 5)(从 other 第 2 位起取 5 字符)insert(s.size(), ...) 模拟 append:它多一次下标合法性检查,且
std::string —— append 非原子,必须加锁或改用线程局部缓冲C++11 起,append 增加了右值引用重载,例如 append(std::string&&),允许窃取资源而非拷贝。但该优化仅在传入临时对象或显式 std::move() 时生效。
下面两行性能差异显著:
s.append(get_temp_string()); // 可能触发移动(若 get_temp_string 返回临时对象) s.append(std::move(t)); // 强制移动 t 的缓冲区
s.append(t))永远走 const lvalue 引用重载,即深拷贝std::move() 显式转换真正影响性能的不是 append 本身,而是你是否让字符串对象始终持有足够容量、是否避免冗余拷贝、以及是否在合适时机移交所有权。这些细节在高吞吐日志、序列化、协议组包等场景里,会直接反映为毫秒级延迟差异。