std::string::size()和length()返回字符数而非字节数;capacity()返回已分配字符容量,需结合sizeof(std::string)估算总内存占用,SSO下仅含对象头大小。

std::string::size() 和 std::string::length() 返回的是字符数,不是内存字节数
很多人以为 str.size() 就是它占的内存大小,其实不是。这个值只表示字符串中字符的个数(即逻辑长度),和实际分配的内存无关。比如一个空字符串 std::string s;,s.size() 是 0,但它内部可能已分配了 15–23 字节(小字符串优化 SSO 空间),也可能完全没分配堆内存。
std::string::capacity() 给出的是当前已分配的总容量(字节)
这是更接近“实际占用内存”的指标,但要注意:它返回的是可容纳字符数的上限,不是真实字节数。因为 std::string 存储的是 char(通常 1 字节/字符),所以对 ASCII 或 UTF-8 编码的字符串,str.capacity() 基本等于已分配的字节数(不含 null terminator)。不过:
-
capacity()不包含小字符串优化(SSO)时的栈内开销——这部分内存不通过堆分配,但确实占用了对象自身空间 - 某些实现会在末尾额外保留一个 null 字节,但
capacity()一般不计入它 - 如果字符串含宽字符(如
std::u16string),每个字符占 2 字节,capacity()返回的是字符数,需乘以sizeof(char16_t)
获取真正内存占用需分情况处理
没有标准接口能一键返回“总内存占用”,因为 std::string 对象本身(含指针、size、capacity 等字段)+ 堆内存(如果有)+ SSO 栈空间,三者来源不同:
- 用
sizeof(std::string)可得对象头大小(通常是 24 或 32 字节,取决于平台和 STL 实现) - 若
str.capacity() > sizeof(std::string),说明启用了堆分配,堆内存 ≈str.capacity()字节(char类型下) - 否则(SSO 激活),所有数据都在对象内部,总内存就是
sizeof(std::string),无需额外堆空间 - 注意:不能直接用
malloc_usable_size或类似函数——std::string不保证暴露其 allocator 的原始指针
简单估算方法(适用于 char 字符串)
多数场景下,你真正关心的是“这个字符串会吃掉多少 RAM”,可以这样粗略估算:
立即学习“C++免费学习笔记(深入)”;
size_t mem_usage = sizeof(std::string);
if (str.capacity() > sizeof(std::string)) {
mem_usage += str.capacity(); // 堆上分配的部分
}
// 注意:这仍不包括 malloc 元数据开销(通常几字节),也不反映内存碎片
更严谨的做法是自定义 allocator 并统计,但代价高;日常调试或性能分析时,用 str.capacity() + sizeof(std::string) 已足够定位大字符串的内存热点。SSO 的边界值(如 15/22/23 字节)因 libstdc++、libc++、MSVC 而异,别硬编码判断。


















