从char*初始化std :: string而不复制

Aku*_*ete 43 c++ string memory-management stl

我有一种情况,我需要处理大量(许多GB)的数据量:

  1. 通过附加许多较小的(C char*)字符串来构建一个大字符串
  2. 修剪弦乐
  3. 将字符串转换为C++ const std :: string进行处理(只读)
  4. 重复

每次迭代中的数据都是独立的.

我的问题是,我想最小化(如果可能消除)堆分配的内存使用量,因为它目前是我最大的性能问题.

有没有办法将C字符串(char*)转换为stl C++字符串(std :: string),而不需要std :: string来内部分配/复制数据?

或者,我可以使用stringstreams或类似的东西来重用大缓冲区吗?

编辑:感谢您的回答,为清楚起见,我认为修改后的问题将是:

如何有效地构建(通过多个附加)一个stl C++字符串.如果在循环中执行此操作,其中每个循环完全独立,我如何重新使用此分配的空间.

pue*_*tzk 22

在不复制数据的情况下,实际上无法形成std :: string.字符串流可能会重用从传递到传递的内存(虽然我认为标准是否真的必须是静音),但它仍然无法避免复制.

解决此类问题的一种常见方法是编写在步骤3中处理数据的代码,以使用开始/结束迭代器对; 然后它可以轻松处理std :: string,chars向量,一对原始指针等.与传递类似std :: string的容器类型不同,它将不再知道或关心内存的分配方式,因为它仍然属于来电者.将这个想法运用到它的逻辑结论是boost :: range,它将所有重载的构造函数添加到仍然让调用者只传递一个字符串/ vector/list /任何类型的容器与.begin()和.end(),或者分开迭代器.

编写了处理代码以处理任意迭代器范围后,您甚至可以编写自定义迭代器(不像听起来那么难,基本上只是一个带有一些标准typedef的对象,以及operator ++/*/=/==/!=重载以获得一个仅向前的迭代器),每当它到达它正在处理的那个片段的末尾时,它会负责前进到下一个片段,跳过空格(我假设这是你修剪的意思).你根本不需要连续组装整个字符串.这是否会取胜取决于你拥有多少片段/片段大小.这基本上是Martin York提到的SGI绳索:一个字符串,其中append形成一个链接的片段列表而不是一个连续的缓冲区,因此适用于更长的值.


更新(因为我仍然看到这个答案的偶尔投票):

C++ 17引入了另一种选择:std :: string_view,它在许多函数签名中替换了std :: string,是对字符数据的非拥有引用.它可以从std :: string隐式转换,但也可以从其他地方拥有的连续数据显式构造,避免不必要的复制std :: string强制.


e.J*_*mes 18

是否可以在步骤1中使用C++字符串?如果使用string::reserve(size_t),可以分配足够大的缓冲区以防止多个堆分配,同时附加较小的字符串,然后您可以在所有剩余步骤中使用相同的C++字符串.

有关reserve功能的更多信息,请参阅此链接.


Mar*_*ork 7

为了帮助实现真正的大字符串,SGI在其STL中拥有类Rope.
非标准但可能有用.

http://www.sgi.com/tech/stl/Rope.html

显然绳索是标准的下一个版本:-)
请注意开发人员的笑话.绳子是一根大绳子.(哈哈) :-)


Dan*_*ker 6

这是一个横向思考的答案,不是直接解决问题,而是围绕它“思考”。可能有用,可能没用……

std::string 的只读处理并不真正需要 std::string 功能的非常复杂的子集。您是否有可能对在 std::strings 上执行所有处理的代码进行搜索/替换,以便它采用其他类型?从一个空白类开始:

类轻量字符串 { };

然后用轻量级字符串替换所有 std::string 引用。执行编译以准确找出需要对轻量字符串进行哪些操作才能将其用作替代品。然后,您可以根据需要使您的实施工作。