views:

2641

answers:

3

I'd like to clear out and reuse an ostringstream (and the underlying buffer) so that my app doesn't have to do as many allocations. How do I reset the object to its initial state?

+2  A: 

Seems to be that the ostr.str("") call does the trick.

Diego Sevilla
Worth pointing out that this won't re-use the underlying buffer from the ostringstream - it just assigns a new buffer. So while you're reusing the ostringstream object, you're still allocating two buffers. I don't think ostringstream is designed for reuse in the manner you intend.
sgreeve
It also doesn't clear out the state, which is what .clear() does. I agree, it really isn't meant to be used like this. Just create a new one to be sure. Only if you profile will you find out if it makes any difference.
Brian Neal
sgreeve, Brian, that's right. Note, however, how the litb's method above requires of the usage of std::ends. It reuses the buffer, but makes you code differently as usual with stringstreams (normally you don't use std::ends).
Diego Sevilla
A: 

You don't. Use two differently named streams for clarity and let the optimizing compiler figure out that it can reuse the old one.

Sebastian Ganslandt
... and of course hope that it does, figure it out that is.
Sebastian Ganslandt
+26  A: 

I've used a sequence of clear and str in the past:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

Which has done the thing for both input and output stringstreams. Alternatively, you can manually clear, then seek the appropriate sequence to the begin:

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

That will prevent some reallocations done by str by overwriting whatever is in the output buffer currently instead. Results are like this:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

If you want to use the string for c-functions, you can use std::ends, putting a terminating null like this:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::ends is a relict of the deprecated std::strstream, which was able to write directly to a char array you allocated on the stack. You had to insert a terminating null manually. However, std::ends is not deprecated, i think because it's still useful as in the above cases.

Johannes Schaub - litb