Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::stringstream with direct output buffer / string result access, avoiding copy?

Is there a canonical / public / free implementations variant of std::stringstream where I don't pay for a full string copy each time I call str()? (Possibly through providing a direct c_str() member in the osteam class?)

I've found two questions here:

  • C++ stl stringstream direct buffer access (Yeah, it's basically the same title, but note that it's accepted answer doesn't fit this here question at all.)
  • Stream from std::string without making a copy? (Again, accepted answer doesn't match this question.)

And "of course" the deprecated std::strstream class does allow for direct buffer access, although it's interface is really quirky (apart from it being deprecated).

It also seems one can find several code samples that do explain how one can customize std::streambuf to allow direct access to the buffer -- I haven't tried it in practice, but it seems quite easily implemented.

My question here is really two fold:

  • Is there any deeper reason why std::[o]stringstream (or, rather, basic_stringbuf) does not allow direct buffer access, but only access through an (expensive) copy of the whole buffer?
  • Given that it seems easy, but not trivial to implement this, is there any varaint available via boost or other sources, that package this functionality?

Note: The performance hit of the copy that str() makes is very measurable(*), so it seems weird to have to pay for this when the use cases I have seen so far really never need a copy returned from the stringstream. (And if I'd need a copy I could always make it at the "client side".)


(*): With our platform (VS 2005), the results I measure in the release version are:

// tested in a tight loop:

// variant stream: run time : 100%
std::stringstream msg;
msg << "Error " << GetDetailedErrorMsg() << " while testing!";
DoLogErrorMsg(msg.str().c_str());

// variant string: run time: *** 60% ***
std::string msg;
((msg += "Error ") += GetDetailedErrorMsg()) += " while testing!";
DoLogErrorMsg(msg.c_str());

So using a std::string with += (which obviously only works when I don't need custom/number formatting is 40% faster that the stream version, and as far as I can tell this is only due to the complete superfluous copy that str() makes.

like image 332
Martin Ba Avatar asked Feb 27 '14 19:02

Martin Ba


People also ask

How do you clean Stringstream?

The clear() member function is inherited from ios and is used to clear the error state of the stream, e.g. if a file stream has the error state set to eofbit (end-of-file), then calling clear() will set the error state back to goodbit (no error). For clearing the contents of a stringstream , using: m. str("");

Can you pass a Stringstream in C++?

Absolutely! Make sure that you pass it by reference, not by value.

What should I use for Stringstream?

To use stringstream, we need to include sstream header file.

How do you use Stringstream STD?

To use stringstream class in the C++ program, we have to use the header <sstream>. For Example, the code to extract an integer from the string would be: string mystr(“2019”); int myInt; stringstream (mystr)>>myInt; Here we declare a string object with value “2019” and an int object “myInt”.


1 Answers

I will try to provide an answer to my first bullet,

Is there any deeper reason why std::ostringstream does not allow direct buffer access

Looking at how a streambuf / stringbuf is defined, we can see that the buffer character sequence is not NULL terminated.

As far as I can see, a (hypothetical) const char* std::ostringstream::c_str() const; function, providing direct read-only buffer access, can only make sense when the valid buffer range would always be NULL terminated -- i.e. (I think) when sputc would always make sure that it inserts a terminating NULL after the character it inserts.

I wouldn't think that this is a technical hindrance per se, but given the complexity of the basic_streambuf interface, I'm totally not sure whether it is correct in all cases.

like image 76
Martin Ba Avatar answered Oct 01 '22 19:10

Martin Ba