如何将 std::string 成员替换为非堆大小限制的字符串?

How can I replace an std::string member with a non-heap limited-size string?

提问人:einpoklum 提问时间:6/19/2021 最后编辑:Tomerikooeinpoklum 更新时间:6/20/2021 访问量:204

问:

我有一个代码库,其中包含一些无处不在的数据结构;并且所述结构具有 std::string 成员。现在,出于某些原因,我希望这个代码库在 std::string 不可用时工作,并且实际上没有动态分配内存(至少不是通常的方式)。我还可以验证该字符串成员的字符串长度永远不会超过 M 个字符(并且 M 很小)。

现在,我应该用什么替换 std::string,这样一方面我就不必做很多重写;另一方面,我的约束条件是否得到满足?

注意:

  • 我无法将字符串的计算移动到编译时。
  • 如果解决方案只有一个普通构造函数和/或构造函数,那也没关系。const char*
  • 涉及使用的解决方案可能是相关的(但我不确定这是否有用)。std::string_view
C++ 字符串 stdstring 堆栈分配

评论

0赞 François Andrieux 6/19/2021
听起来你只是想要一个.如果你想保留一个类似 - 的接口,你可以把它包装在一个类中。但请注意,此更改可能会使您的类型对移动的友好性大大降低,对容器的友好性降低,并且通常会显着增加其大小。std::array<char, M + 1>std::string
0赞 eerorika 6/19/2021
@FrançoisAndrieux 鉴于“M 很小”并且是较大类型(24..32 字节),根据它有多小,移动友好性和类规模可能没有变化,甚至没有改善。std::string
0赞 Galik 6/19/2021
您可能只需要一个新的字符串分配器。
3赞 Drew Dormann 6/19/2021
Boost 有一种叫做 static_string 的东西,其存储相当于一个数组,以及一个努力匹配的接口。std::string
1赞 Mooing Duck 6/19/2021
我还有一个自定义small_string,它显然类似于 boost 。static_string

答:

3赞 eerorika 6/19/2021 #1

char[M + 1]可能是一个体面的、简单的调查选择。重写量可能或多或少,具体取决于到目前为止您如何使用字符串成员。

如果经常使用成员的“std::stringiness”,那么您可以通过实现一个自定义类来减少重写量,该类提供与 类似的接口,但在内部使用 . 德鲁·多尔曼(Drew Dormann)提到的是此类的模板。std::stringchar[M + 1]boost::static_string

P.S. 如果您仍然可以使用并且仅被限制使用动态内存,那么您可以继续使用自定义分配器,正如 Galik 所提到的。std::stringstd::string

评论

0赞 einpoklum 6/19/2021
我希望避免“滚动我自己的”类似字符串的类。 可能是相关的,但可能有点矫枉过正,因为它是一堆东西的模板;我需要要么拖入所有 boost,要么将其从 Boost 中撕掉。可能仍然这样做。boost::static_string
1赞 Mooing Duck 6/19/2021
@einpoklum:“该库可在两种不同的模式下使用:独立模式和 Boost 相关模式。此库默认为 Boost 依赖模式;独立模式是通过使用配置宏来选择加入的。boost.org/doc/libs/1_75_0/libs/static_string/doc/html/...... BOOST_STATIC_STRING_STANDALONE
0赞 einpoklum 6/19/2021 #2

一个最麻烦的潜在解决方案可以利用您的案例的具体情况,为了简单而牺牲通用性:

你写的要替换的字符串实际上是另一个结构的成员。正如@eerorika所建议的那样,这已经允许使用结构的数组成员,而不必担心数组衰减。但是 - 数组不是 std::string 的接口。

你说你没有看到一个会有什么用 - 那是因为没有存储空间可以与之配套。std::string_view

好吧,将两者结合起来!...不,不要编写同时具有存储和字符串接口的新类。相反,使用新的字段名称向结构中添加一个字段,并使用原始字段名称作为查看数组string_view(当然要有适当的长度)!char [M+1]

这使构造和赋值变得有点复杂 - 即它不再是微不足道的成员构造 - 但您将能够传递此对象并使用与以前相同的字段,例如 std::string。

  struct ubiquitous {
     // other members
     char[M+1] string_data;
     std::string_view original_field;

     // apply rule of 5: ctor, move ctor, assignment, move assignment
     // and a trivial dtor (at least for your two fields)
     // ... so, a "rule of 4" in this case
  };

如果你没有可用的代码,即 C++17 之前的代码,那么你可以获得 Martin Moene 的向后移植string_view (GitHub)。string_view