Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ std::ostringstream vs std::string::append

Tags:

c++

string

stream

In all examples that use some kind of buffering I see they use stream instead of string. How is std::ostringstream and << operator different than using string.append. Which one is faster and which one uses less resourses (memory).

One difference I know is that you can output different types into output stream (like integer) rather than the limited types that string::append accepts.

Here is an example:

std::ostringstream os; os << "Content-Type: " << contentType << ";charset=" << charset << "\r\n"; std::string header = os.str(); 

vs

std::string header("Content-Type: "); header.append(contentType); header.append(";charset="); header.append(charset); header.append("\r\n"); 

Obviously using stream is shorter, but I think append returns reference to the string so it can be written like this:

std::string header("Content-Type: "); header.append(contentType)   .append(";charset=")   .append(charset)   .append("\r\n"); 

And with output stream you can do:

std::string content; ... os << "Content-Length: " << content.length() << "\r\n"; 

But what about memory usage and speed? Especially when used in a big loop.

Update:

To be more clear the question is: Which one should I use and why? Is there situations when one is preferred or the other? For performance and memory ... well I think benchmark is the only way since every implementation could be different.

Update 2:

Well I don't get clear idea what should I use from the answers which means that any of them will do the job, plus vector. Cubbi did nice benchmark with the addition of Dietmar Kühl that the biggest difference is construction of those objects. If you are looking for an answer you should check that too. I'll wait a bit more for other answers (look previous update) and if I don't get one I think I'll accept Tolga's answer because his suggestion to use vector is already done before which means vector should be less resource hungry.

like image 652
NickSoft Avatar asked Nov 07 '13 19:11

NickSoft


People also ask

What is the difference between std::string and string?

There is no functionality difference between string and std::string because they're the same type.

Why do we use std::string?

std::string class in C++ C++ has in its definition a way to represent a sequence of characters as an object of the class. This class is called std:: string. String class stores the characters as a sequence of bytes with the functionality of allowing access to the single-byte character.

Is std :: To_string slow?

std::to_string is no longer a performance disaster as it used to be, at least on integer input. It is still affected by the global locale giving unpredictable results and nondeterministic performance and should generally be avoided but its an interesting development nevertheless.

Is std::string movable?

Yes, std::string (since C++11) is able to be moved i.e. it supports move semantics.


1 Answers

constructing a stream object is a significantly more complex operation than constructing a string object, because it has to hold (and, therefore, construct) its std::locale member, among other things needed to maintain state (but the locale is by a large margin the heaviest).

Appending is similar: both maintain a contiguous array of characters, both allocate more when the capacity is exceeded. The only differences I can think of is that when appending to a stream, there is one virtual member function call per overflow (in addition to memory allocation/copying, which dominates overflow handling anyway), and operator<< has to do some extra checks of the stream state.

Also, note that you're calling str(), which copies the entire string one more time, so based on what your code is written to do, the stream example does more and should be slower.

Let's test:

#include <sstream> #include <string> #include <numeric>  volatile unsigned int sink; std::string contentType(50, ' '); std::string charset(50, ' '); int main() {  for(long n = 0; n < 10000000; ++n)  { #ifdef TEST_STREAM         std::ostringstream os;     os << "Content-Type: " << contentType << ";charset=" << charset << "\r\n";     std::string header = os.str(); #endif #ifdef TEST_STRING     std::string header("Content-Type: ");     header.append(contentType);     header.append(";charset=");     header.append(charset);     header.append("\r\n"); #endif     sink += std::accumulate(header.begin(), header.end(), 0);  } } 

that's 10 million repetitions

On my Linux, I get

                   stream         string g++ 4.8          7.9 seconds      4.4 seconds clang++/libc++  11.3 seconds      3.3 seconds 

so, for this use case, in these two implementations, strings appear to work faster, but obviously both ways have a lot to improve (reserve() the string, move stream construction out of the loop, use a stream that doesn't require copying to access its buffer, etc)

like image 98
Cubbi Avatar answered Oct 16 '22 00:10

Cubbi