I have noticed lately that a lot of C++ programmers are still using strstream instead of stringstream. I am sure that this is partially a consequence of the fact that many of the versions of C++ libraries out there still do not support the new Standard IOStreams model including stringstream. Unfortunately, I also suspect that it is plain old laziness on the part of a lot of programmers. After all, even though strstream is deprecated in the Standard, that just means that it may be taken out sometime in the distant future, but is still guaranteed to be there in the near future, so why not continue to use it?. This is not a good idea. There are some good reasons that strstream is deprecated in the Standard and stringstream is the preferred mechanism if you need to do in-memory I/O.
Ideally, you could just switch from including <strstream.h> (or <strstream>) to including <sstream> and recompile, but there a few differences between strstream and stringstream, some minor, some major. One of the minor differences is that stringstream::str returns a string object whereas strstream::str returns a const char*. It is the user's responsibility to ensure that the character array returned by strstream is null terminated. This is usually accomplished with the ends manipulator, as in the following
strstrm << "..." << ends;Since stringstream returns a string object, this is not only unnecessary, but will result in putting a null character in the string, causing it to be one longer than expected.
The most important difference between strstream and stringstream is that str called on a strstream "freezes" the internal buffer. This makes it the user's responsibility to delete the memory reference returned by str. Unfortunately, you can not just automatically call delete[] on this pointer. A strstream can be passed a buffer to use instead of allocating an internal buffer. This may be a local buffer not allocated from the free store. Therefore, after a call to str, you have to know how the strstream was constructed before you can correctly decide what to do with the buffer. In practice, strstream is a fertile source of memory leaks (as I can attest from annoying personal experience). I would say this is the primary reason that strstream was deprecated in favor of stringstream.
While stringstream is both more convenient and safer to use than strstream, it does have one drawback. Anyone who knows almost anything about how the IOStreams library is organized knows that it consists of two layers: the formatting layer and the buffering layer. stringstream is no exception. Given this little knowledge, it is easy to assume that the stringbuf component would accept the nomination of a user-supplied string as the source or destination buffer. This is not the case, however. An ostringstream constructor does exist that takes a string as an argument, but if you look at the constructor's signature, you will see that it actually takes a const string&. The contents of any provided string are simply used to initialize the internal buffer. This means that stringstream, or more precisely stringbuf, always manages an internal buffer. This, plus the fact that the stringstream::str function returns a string object, means that stringstream doesn't leak memory. On the other hand, it also means that whenever you use a stringstream to parse some existing string of data, you will probably pay the overhead of a memory allocation and copying of the data itself. Likewise, if you have an existing buffer that you would just like to format some data into, you will also pay for an extra allocation and copy.
So, especially when it comes to parsing some existing string, strstream actually looks like a better choice than stringstream. Unfortunately, strstream does not work very well for the opposite case of formatting data directly into an existing string. Finally strstream is deprecated, and when developing new code there is no excuse for using deprecated features (provided the compiler and library in use support the newer alternatives, of course). By creating my own String_stream<> template, I have solved the dilemma. If I need a stream that manages its own buffer, I use the Standard stringstream. If I have a string that I want to parse in place, or when I want to avoid the overhead of extra memory allocations and data copying, I use my String_stream template. In both cases, the responsibility for memory management in clearly defined: stringstream does its own, and String_stream depends entirely upon the instantiating string type. And once again, the Standard Library proves itself to be a well designed framework for extensions, even if it doesn't provide the optimal solution for every problem.