如何实现仅在堆栈上分配的字符串

sbi*_*sbi 8 c++ string allocator stack-allocation

在大约十年前的一个项目中,我们发现std::vector动态分配导致了严重的性能损失.在这种情况下,它分配了许多小向量,因此快速解决方案是编写一个类似于向量的类,包装在基于堆栈的预分配char数组中,用作其容量的原始存储.结果是static_vector<typename T, std::size_t Max>.如果您了解一些基础知识,这样的事情很容易写,你可以在网上找到很多这样的野兽.事实上,现在也有一个提升.

现在在嵌入式平台上工作,我们碰巧需要一个static_basic_string.这将是一个字符串,它预先在堆栈上分配固定的最大内存量,并将其用作容量.

起初我认为这应该相当容易(static_vector毕竟它可以基于现有的),但再看看std::basic_string界面我不再那么肯定了.它比std::vector界面更复杂.特别是实现find()功能系列std::basic_string不仅仅是一项繁琐的工作.

这让我再次思考.毕竟,这就是创建分配器的原因:基于newdelete使用其他方法替换分配.但是,要说分配器接口不实用将是轻描淡写.有一些文章在那里解释它,但有一个原因,我在过去的15年中看到这么的本土分配器.

所以这是我的问题:

如果你必须实现一个basic_string相似的,你会怎么做?

  • 写你自己的static_basic_string
  • 写一个分配器来传递给std::basic_string
  • 做一些我没想到的事情?
  • 使用来自提升的东西我不知道?

与往常一样,对我们来说存在相当重要的限制:在嵌入式平台上,我们与GCC 4.1.2绑定,因此我们只能使用C++ 03,TR1和boost 1.52.

Jam*_*nze 4

第一个问题是:你使用了多少额外的接口?大多数std::string附加接口都可以使用<algorithm>(例如 std::findstd::find_ifstd::search)中的函数轻松实现,并且在很多情况下,其中有很大一部分无论如何都不会被使用。只需根据需要实施即可。

我认为你不能使用自定义分配器来完成这项工作。获得“堆栈上”内存的唯一方法是将其声明为自定义分配器的成员,这在复制它们时会产生各种问题。分配器必须是可复制的,并且副本必须是幂等的。

也许你可以在网上找到一个免费的实现, std::string它使用小字符串实现;然后修改它,使截止大小(超过它使用动态分配)大于您实际使用的任何字符串。(标准库有多种开源实现;与 g++ 一起提供的实现仍然使用 COW,但我怀疑其他大多数都使用 SSO。)

  • @sbi 我也差不多,我做了很多解析。99% 的情况下,我只会使用 `&lt;algorithm&gt;` 中的函数。同样,像“插入”或“替换”这样的事情似乎也很少见;我通常会构建一个副本,然后进行附加。 (2认同)