C++小字符串优化 (SSO) 如何与容器配合使用?

How could C++ Small String Optimized (SSO) work with containers?

本文关键字:优化 字符串 SSO C++      更新时间:2023-10-16

SSO解释说小字符串是在堆上分配的:好的,但是当在容器内构造时,这些内容不应该在堆栈上,因为容器可以在函数中创建并返回,而函数堆栈会过时。

所以我想 SSO 不适用于 STL 容器,是吗?

"小字符串"和"大字符串"之间的区别不在于将其存储在堆栈或堆上之间的区别。相反,不同的是间接程度

这意味着std::string对象可以保存指向实际字符串数据的指针,该指针可以是(几乎)任何长度,但具有间接动态内存的所有缺点 - 分配,解除分配,缓存未命中等。

或者,SSO 允许std::string将小字符串"就地"存储在std::string对象内部,无论它被分配到何处。如果对象位于某个容器(在堆上)中,则字符串将位于该容器中,但它不需要像大字符串那样的另一个间接寻址。

让我们用vectorstring做一个例子。

  1. 请参阅我对"c ++ Vector,每当它在堆栈上扩展/重新分配时会发生什么?"的回答,看看vector通常"看起来像什么"。

  2. 如果将string存储在vector中,则所有string实例都将位于堆上。

  3. 字符串实例本身可以

    • 在对象实例 (SSO) 中包含字符串数据本身,或者
    • 在堆上分配内存以存储内容。
  4. vector类不关心string类将其数据存储在哪里。 它只保存自行管理数据的对象。

SSO 不会影响在容器中存储string

PS:当然可以从函数返回堆栈对象。函数堆栈将"超出范围",但返回值将保留。否则你甚至不能回来int

SSO并不意味着无论如何string内容都在堆栈上。这只是意味着(小字符串)数据存储在string实例中。因此,如果实例在堆栈上,则数据在堆栈上。如果对象在堆上,则数据也在堆上。

你当然可以编写一个具有"小对象优化"的类似矢量的类,如果对象很小而且很少,它会将它们存储在内部(在容器对象本身内),否则将它们存储在堆上(就像std::vector现在所做的那样)。

但是,由于对容器的要求,目前无法实现标准库中的容器。特别是,[container.requirements.general]/9说:

在交换之前引用一个容器中的元素的每个迭代器都应在交换后引用另一个容器中的相同元素。

这很难用小对象优化来实现,而且该要求不适用于basic_string