How to reuse an ostringstream?

C++StlResetOstringstream

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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

Solution 3 - C++

If you're going to clear the buffer in a way that will cause it to be cleared before it's first use, you'll need to add something to the buffer first w/ MSVC.

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
	template<class T>
	inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

Solution 4 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontwkView Question on Stackoverflow
Solution 1 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 2 - C++Diego SevillaView Answer on Stackoverflow
Solution 3 - C++Unkle GeorgeView Answer on Stackoverflow
Solution 4 - C++Sebastian GanslandtView Answer on Stackoverflow