So istringstream
copies the contents of a string when initialised, e.g
string moo("one two three four");
istringstream iss(moo.c_str());
I was wondering if there's a way to make std::istringstream
use the given c_str
as its buffer without copying things. This way, it won't have to copy large bits of memory before passing the std::istringstream&
to functions that take istream&
as an argument.
What I've been trying to do is convert some functions which only take std::ifstream&
arguments (they're mostly parsers) into taking istream&
as well. Would I have to make my own istream
subclass for this?
There's only a copy because the parameter you pass, a
const char*
, requires conversion to the argument type of the istringstream constructor.Just pass in the
string
without callingc_str()
.Well ok, that doesn't prevent copying completely, but it eliminates an unnecessary copy. To completely eliminate the copy, you'd have to rewrite
std::stringbuf
, which specifically avoids working directly on thestring
you give it.the deprecated
istrstream
supports this feature.It's fairly trivial to write a basic
std::streambuf
class that reads from a given memory area. You can then construct anistream
from this and read from that.initializing a C++ std::istringstream from an in memory buffer?
Note that the lifetime of the buffer pointed to be
c_str()
is very limited, though, and there's no guarantee that a call toc_str()
want cause some copying although I don't know of any implementations where it does.It depends on what a std::string does. According to 27.2.1/1
The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage.
Since the class must use an object it must copy construct the string into that object.So the real question is not whether a
stringstream
copies the contents, but whether copy constructing a string will copy the contents or implement some sort of copy-on-write scheme.Using
istringstream
is not a satisfactory solution, because this copies the entire buffer.A previous answer suggests the deprecated
istrstream
, but as this generates warnings and may be removed in future, a better solution is to use boost::iostreams:This avoids copying the buffer in the same way
istrstream
did, and saves you having to write your own stream class.