小编典典

std::string 上下文中首字母缩写词 SSO 的含义

all

关于优化和代码风格的 C++ 问题中,有几个答案在优化std::string.
在这种情况下,SSO 是什么意思?

显然不是“单点登录”。也许是“共享字符串优化”?


阅读 80

收藏
2022-08-05

共1个答案

小编典典

背景/概述

对自动变量的操作(“从堆栈”,这是您在不调用malloc/的情况下创建的变量new)通常比那些涉及自由存储(“堆”,这是使用创建的变量)快得多new。但是,自动数组的大小在编译时是固定的,但来自自由存储的数组的大小不是。此外,堆栈大小是有限的(通常为几个
MiB),而免费存储仅受系统内存的限制。

SSO 是短/小字符串优化。Astd::string通常将字符串存储为指向空闲存储(“堆”)的指针,这提供了与调用new char [size].
这可以防止非常大的字符串的堆栈溢出,但它可能会更慢,尤其是复制操作。作为一种优化,许多实现std::string创建一个小的自动数组,比如char [20]. 如果您有一个 20
个字符或更小的字符串(在此示例中,实际大小会有所不同),它将直接将其存储在该数组中。这完全避免了调用的需要new,从而加快了速度。

编辑:

我没想到这个答案会如此受欢迎,但既然如此,让我给出一个更现实的实现,但需要注意的是,我从未真正“在野外”阅读过任何 SSO 的实现。

实施细节

a 至少std::string需要存储以下信息:

  • 规模
  • 容量
  • 数据的位置

大小可以存储为
astd::string::size_type或指向末尾的指针。唯一的区别是您是否希望在用户调用时必须减去两个指针,或者在用户调用时向指针size添加
a 。容量也可以以任何一种方式存储。size_type``end

你不用为你不使用的东西付费。

首先,根据我上面概述的内容考虑简单的实现:

class string {
public:
    // all 83 member functions
private:
    std::unique_ptr<char[]> m_data;
    size_type m_size;
    size_type m_capacity;
    std::array<char, 16> m_sso;
};

对于 64 位系统,这通常意味着std::string每个字符串有 24 个字节的“开销”,另外还有 16 个字节用于 SSO
缓冲区(由于填充要求,此处选择 16 个而不是 20 个)。存储这三个数据成员加上一个本地字符数组是没有意义的,就像在我的简化示例中一样。如果m_size <= 16,那么我会将所有数据放入m_sso,所以我已经知道容量并且我不需要指向数据的指针。如果m_size > 16,那么我不需要m_sso。在我需要所有这些的地方绝对没有重叠。一个不浪费空间的更智能的解决方案看起来更像这样(未经测试,仅用于示例目的):

class string {
public:
    // all 83 member functions
private:
    size_type m_size;
    union {
        class {
            // This is probably better designed as an array-like class
            std::unique_ptr<char[]> m_data;
            size_type m_capacity;
        } m_large;
        std::array<char, sizeof(m_large)> m_small;
    };
};

我假设大多数实现看起来更像这样。

2022-08-05