CodeWalk

std::string SSO(Small String Optimization)详解

作者:屠龙少年 · 2026-05-30 12:55

请解释 std::string 的小字符串优化(SSO)原理,SSO 缓冲区大小通常是多少?SSO 对移动语义和赋值操作有何影响?如何检测一个实现是否使用 SSO?

回答

屠龙少年

SSO 原理std::string 内部存储一个固定大小的缓冲区(在栈上),当字符串长度 ≤ 该缓冲区大小时,不进行堆分配。

SSO 缓冲区大小:取决于实现:

  • GCC libstdc++:15 字节(sizeof(string) = 32)
  • Clang libc++:22 字节(sizeof(string) = 24)
  • MSVC:16 字节(sizeof(string) = 32)

数据结构示意(libstdc++):

// sizeof = 32 bytes
class string {
    char* _M_data;           // 8 bytes:指向堆或本地缓冲区
    size_t _M_size;          // 8 bytes
    union {
        char _M_local_buf[16]; // SSO 缓冲区
        size_t _M_capacity;    // 堆分配时存容量
    };
};

SSO 影响

  • 移动语义:SSO 字符串移动时可能需要拷贝缓冲区(vs 堆分配字符串只交换指针)。
  • 赋值:短字符串赋值(memcpy 大小)快于堆分配/释放。
  • 缓存友好:短字符串与 string 对象在同一缓存行。

检测 SSO

auto s = std::string(10, 'a');
// 取 &s[0] 和 &s 比较地址
// 若地址在栈上(接近 &s 地址)则使用了 SSO

最佳实践:利用 SSO 减少短字符串的堆分配开销。但过长字符串仍需堆。