I am migrating an old code base from using a custom implementation of strings to use std::string. One of our engineers is concerned that this could lead to a performance issue where we are using += and + to concatenate relatively long strings. His particular concern is how the memory is allocated as the string grows dynamically, and he suggested that stringstream would perform better in this regard. For those of you tempted to respond "benchmark then optimize" or sentiments to those effect -- I do of course agree, and that's the plan. I'm just wondering about the theory.
I did a little searching for this issue, and ran into this question: Efficient string concatenation in C++, which is getting a little dated.
Now I'm wondering: Is the memory allocation algorithm for string += really different than that for string stream? What about the copy issues raised in the above question -- have these changed with c++ 11/14?
The stringstream class in C++ allows a string object to be treated as a stream. It is used to operate on strings. By treating the strings as streams we can perform extraction and insertion operation from/to string just like cin and cout streams.
string stream is slow. Quite very slow. If you are writing anything performance critical that acts on large data sets ( say loading assets after a level change during a game ) do not use string streams.
Strings, C++'s std::strings are mutable, and therefore can be built through simple concatenation just as fast as through other methods.
Very Informally: A string is a collection of characters, a stream is a tool to manipulate moving data around. A string stream is a c++ class that lets you use a string as the source and destination of data for a stream.
Is the memory allocation algorithm for string += really different than that for string stream?
Yes.
A stringstream writes into a stringbuffer, which usually means a linked list of buffers. Memory is not continuous, and it requires no reallocations as the buffer grows.
A string on the other hand, allocates memory in a single block (as needed, and sometimes preemptively).
The most efficient solution is probably to precompute the resulting string size, allocate manually the result, then fill it in (using std::string::operator +=
).
That said, I would just write into std::ostringstream and take the result at the end (but YMMV).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With