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

标签 c++ string memory-management stl

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

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

每次迭代的数据都是独立的。

我的问题是,我想尽量减少(如果可能的话消除)堆分配的内存使用,因为它目前是我最大的性能问题。

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

或者,我可以使用字符串流或类似的东西来重新使用大缓冲区吗?

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

如何有效地构建(通过多个附加)STL C++ 字符串。如果在一个循环中执行这个 Action ,每个循环都是完全独立的,我怎样才能重新使用这个分配的空间。

最佳答案

如果不复制数据,您实际上无法形成 std​​::string。一个字符串流可能会重复使用一遍又一遍的内存(尽管我认为标准对它是否真的必须如此保持沉默),但它仍然无法避免复制。

解决此类问题的常用方法是编写处理步骤 3 中的数据的代码,以使用开始/结束迭代器对;那么它可以很容易地处理一个 std::string、一个字符 vector 、一对原始指针等。与传递它像 std::string 这样的容器类型不同,它不再知道或关心内存是如何分配的,因为它仍然属于调用者。将这个想法带到合乎逻辑的结论是boost::range ,它添加了所有重载的构造函数,仍然让调用者只需传递带有 .begin() 和 .end() 的字符串/vector/列表/任何类型的容器,或单独的迭代器。

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


更新(因为我仍然偶尔看到对此答案的支持):

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

关于c++ - 从 char* 初始化 std::string 而不复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/361500/

相关文章:

c - C 中使用指针的字符串连接

memory-management - Linux 内核中的 Slab 和 Slub 分配器如何选择?

c++ - 字符串分配的双重释放或损坏错误

C++ 结合静态和动态多态性来创建 "Hyper Polymorphism"?

c++ - 具有多个成员的高效运算符<

c# - string.Empty vs null。你用哪个?

string - 快速 SQL 问题

c++ - 二叉搜索树实现 C++ 运行时错误

c - 大小未知的动态数组

copy_to_user 一个包含数组(指针)的结构