从char *初始化std :: string而不复制
我有一种情况,我需要处理大量(GB)的数据量:
- 通过附加许多较小的(C char *)string来构build一个大的string
- 修剪string
- 将string转换为C ++常量std :: string进行处理(只读)
- 重复
每次迭代中的数据是独立的。
我的问题是,我想尽量减less(如果可能的话)堆分配的内存使用量,因为它目前是我最大的性能问题。
有没有办法将Cstring(char *)转换成stl C ++string(std :: string),而不需要std :: string内部分配/复制数据?
或者,我可以使用stringstreams或类似的东西重新使用一个大的缓冲区?
编辑:谢谢你的答案,为了清晰起见,我认为一个修改后的问题是:
我怎样才能有效地(通过多个附加)生成一个stl C ++string。 如果在一个循环中执行这个动作,每个循环都是完全独立的,我怎样才能重新使用这个分配的空间。
在步骤1中是否可以使用C ++string? 如果使用string::reserve(size_t)
,则可以分配足够大的缓冲区来防止多个堆分配,同时附加较小的string,然后可以在所有其余步骤中使用相同的C ++string。
有关reserve
function的更多信息,请参阅此链接 。
如果不复制数据,实际上不能形成std :: string。 一个stringstream可能会重复传递的内存(虽然我认为标准是无声的),但它仍然不能避免复制。
解决这类问题的一种常见方法是编写在第3步中处理数据的代码,以使用开始/结束迭代器对; 那么它可以很容易地处理一个std :: string,一个字符向量,一对原始指针等。不像传递一个像std :: string这样的容器types,它不再知道或关心内存如何分配,因为它仍然属于呼叫者。 把这个想法推广到它的逻辑结论是boost :: range ,它增加了所有的重载构造函数,让调用者只是通过.begin()和.end()传递一个string/ vector / list /任何types的容器,或者分开迭代器。
写完你的处理代码后,你可以编写一个自定义的迭代器(不像听起来那么辛苦,基本上只是一个带有一些标准typedef的对象,而operator ++ / * / = / == / !=重载获得一个只进栈迭代器),每次到达它正在处理的那个末尾时,都会照顾到下一个碎片,跳过空白(我假设你是这个意思)。 那你根本就没有必要把整个琴弦连成一团。 这是否是一场胜利取决于你有多less碎片/多less碎片。 这实际上是Martin York提到的SGI绳索:一个string,其中append形成一个片段的链接列表而不是连续的缓冲区,因此适用于更长的值。
更新 (因为我仍然偶尔看到这个答案upvotes):
C ++ 17引入了另一个select: std :: string_view ,它取代了许多函数签名中的std :: string,是对字符数据的非拥有引用。 它可以隐式地从std :: string转换,但也可以从其他地方拥有的连续数据显式构造,避免不必要的复制std :: string。
为了帮助真正的大stringSGI的STL中有类Rope。
不标准,但可能是有用的。
http://www.sgi.com/tech/stl/Rope.html
显然绳子是在标准的下一个版本:-)
注意开发人员的笑话。 一根绳子是一根大绳子。 (哈哈) :-)
这是一个横向的思考答案,不是直接解决问题,而是“思考”问题。 可能有用,可能不会…
std :: string的只读处理实际上并不需要std :: string的特性的一个非常复杂的子集。 有没有可能做search/replace上执行所有处理的std ::string的代码,所以它需要一些其他types? 从一个空白的课程开始:
class lightweight_string {};
然后用lightweight_stringreplace所有的std :: string引用。 执行一个编译,以确定在lightweight_string上需要什么操作,以充当drop-inreplace。 然后,你可以让你的实现工作,但你想要的。
每个迭代是否足够独立,您可以为每个迭代使用相同的std :: string? 人们会希望你的std :: string实现足够聪明,可以重新使用内存,如果你为它指定了一个const char *的话。
将char *分配到std :: string中必须至less复制数据。 内存pipe理是使用std :: string的主要原因之一,所以你不能重写它。
在这种情况下,直接处理char *可能会更好,而不是将其分配给std :: string。