




std::string::capacity() 返回当前分配但未使用的字符空间大小(以字节计),单位是 size_type;它反映底层缓冲区能容纳多少字符而不触发重新分配,空字符串的 capacity() 可能非零,clear() 不降低 capacity(),reserve() 仅在请求容量大于当前 capacity() 时重分配。
capacity() 返回当前分配但未使用的字符空间大小(以字节计),单位是 size_type,不是字符串实际长度。它反映底层缓冲区能容纳多少字符而不触发重新分配。
常见误解是认为 capacity() 等于 size() 或受构造方式“固定”。实际上:
capacity() 可能非零(如 GCC 的 SSO 实现常为 15 或 22)std::string s = "hello" 构造后,capacity() 可能大于 size(),也可能相等,取决于编译器和优化级别clear() 不会降低 capacity();内存仍保留reserve() 显式要求底层分配至少指定数量的字符空间。它只增不减,且仅在请求容量 > 当前 capacity() 时才真正重分配。
典型使用场景:已知后续要拼接大量数据(如读取文件、解析日志行),提前预留可避免多次 realloc + memcpy。
注意点:
reserve(n) 中 n 是字符数,不是字节数(UTF-8 多字节字符仍按一个 char 计)n ,调用无任何开销,也不改变现有内容
size() 不变,字符串内容不变,只是缓冲区变大了reserve() 来“截断”字符串——那是 resize() 或 shrink_to_fit() 的事reserve() 是向上调整容量上限,shrink_to_fit() 是向下尝试释放多余内存(C++11 起)。但后者是“提示”,实现可忽略。
示例对比:
std::string s = "1234567890"; s.reserve(100); // capacity ≥ 100(通常就是 100) s += "xxxxxxxxxx"; // 追加 10 字符,size=20,capacity 仍 ≥ 100 s.shrink_to_fit(); // capacity 可能回落到 20 或略高,但不保证
常见误用:
reserve() → 频繁分配反而更慢shrink_to_fit() 一定生效 → 在 libstdc++ 中可能无效,在 MSVC 中较可靠reserve(s.size() + N) → 容量阶梯增长,不如一次性预估总长几乎所有主流 STL 实现(libstdc++、libc++、MSVC)都对小字符串启用 SSO(Short String Optimization)。这意味着:
capacity() 返回的是 SSO 缓冲区总长(含终止符位),不是堆上容量reserve() 在 SSO 区域内调用无效(因为没堆内存可扩);一旦超过 SSO 阈值,首次扩容才真正 malloc验证方式:
std::string s; std::cout << "empty capacity: " << s.capacity() << "\n"; // 常见输出 15 或 22 s = std::string(20, 'x'); // 强制堆分配 std::cout << "20-char capacity: " << s.capacity() << "\n"; // 通常 ≥ 20,可能是 32/48/64
所以别依赖 capacity() 判断是否“已堆分配”——它只告诉你当前可用空间,不管来源。
真正需要预分配时,先估算最大长度,再一次性 reserve();频繁小量追加又不确定总量,不如交给默认策略。SSO 让小字符串几乎零成本,而盲目 reserve 反而可能绕过它、强制堆分配
