字符串的内存高效向量

Posted

技术标签:

【中文标题】字符串的内存高效向量【英文标题】:Memory efficient vector of strings 【发布时间】:2019-10-09 09:29:42 【问题描述】:

理论上是否有可能使用一些分配器来获得一个内存高效的 STL(和/或 Boost)字符串向量,例如:

using String = std::basic_string<char, std::char_traits<char>, SomeAllocMaybe;
using Vector = std::vector<String, SomeOtherAllocMaybe>;

Vector vec( /* an allocator eventually */ );
vec.emplace_back("first string longer than SSO");
vec.emplace_back("second string");
vec.emplace_back("third string longer than SSO");

将导致内存中只有一个紧凑的连续数据块,如下所示:

"first string longer than SSO'\0'second string'\0'third string longer than SSO'\0'"

【问题讨论】:

在您的场景中,当您执行 vec[1].append("boom") 时会发生什么? 这不是一个真正的向量,更像是一个串联的字符串,而且这已经存在,它是std::string ;) 理论上,当然。然而,这需要太多关于编译器如何实现 std::string 的假设。如果你真的需要你指定的内存布局,可能值得为它滚动你自己的类。例如 GCC:***.com/q/5058676/5343120 理论上是可以的,是的。但你真正需要的是什么?您是否只需要将字符串放在同一内存段中,或者您是否也不想避免“指针 deref”?在第一种情况下 - 附加到一个字符串可能会移动到不同的内存段。 使用 STL/Boost 会对这些类的底层实现做很多假设。我宁愿自己实现。 【参考方案1】:

您可以使用boost interprocess allocators 来做到这一点。

【讨论】:

你能说得更具体点吗?看起来图书馆里有很多不同类型的设施,以及不同的组合方式。【参考方案2】:

不,std::vectorstd::basic_string 无法做到这一点。 std::vector 包含一个连续的元素序列 (std::basic_strings),std::basic_string 不会以这种特殊方式在内存中布局。它存储大小信息,或者至少存储标签位以区分长字符串和短字符串。

如果你想要连续的内存,直接使用一个std::basic_string。将一个字符附加到字符串具有摊销常数时间复杂度,因此连接字符串将是有效的。

【讨论】:

如果字符串之间有一些小的附加信息,我想我可以。不能说它们之间有整个 SSO 块,但我们假设它也很好。【参考方案3】:

是的,这绝对是可能的 - 话虽如此,您可能不希望两者都使用相同的分配器/内存段,因为这会使事情变得复杂 - 主要是当向量需要重新分配时,您必须移动并可能重新分配所有内容.因此,您需要特别小心,您需要再次定制以满足您的特定需求。因此,只考虑字符串堆要简单得多,然后您就不必担心 根据您的需要进行配置 部分。我假设字符串需要使用,而不仅仅是 const - 因为这是可以非常不同地处理的特殊情况。

【讨论】:

以上是关于字符串的内存高效向量的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的编译器对 c 字符串类型的向量存在内存问题?

首先创建字符串然后通过移动语义将其添加到向量或在向量中创建元素是不是具有内存效率?

为字符串向量预分配内存(C++ vector<string>)

c++ boost进程间交换(复制)非共享和共享字符串向量

高效网页去重算法-SimHash

Haskell 中的内存高效字符串