I'll admit that I don't understand it either. I can't find any
default constructor at all for std::istream
, and I would think
you would want one if you want to create a bidirectional stream,
because of the strange way std::ios_base
works: the
constructor does not initialize anything, but the derived
class must call std::ios_base::init
explicitly in its
constructor. When multiple inheritance is involved (i.e.
bidirectional IO, where the class derives from both
std::istream
and std::ostream
), I would expect only the most
derived class to call std::ios_base::init
. (In
std::iostream
, std::ios_base::init
will be called twice.)
In fact, before looking it up in the standard, I was about to
answer that the default constructor was protected, because it
didn't call std::ios_base::init
, and using it directly, rather
than in a derived class, would result in an uninitialized
stream.
Anyhow, your immediate problem has a simple solution:
std::ostream out( NULL );
Also: the function you need to set up its sink later is the
non-const version of rdbuf()
, not copyfmt()
. rdbuf()
is
used to read and to set the pointer to the streambuf
,
copyfmt()
copies the formatting flags, but does not touch
the pointer to streambuf
.
So you can do things like:
std::ostream out( NULL );
// ...
std::filebuf fileBuffer;
if ( filenameGiven ) {
fileBuffer.open( filename.c_str(), std::ios_base::out );
}
if ( fileIsOpen() ) {
out.rdbuf( &fileBuffer );
} else {
out.rdbuf( std::cout.rdbuf() );
}
(I do this a lot. In fact, I thought that it was the usual
idiom when you didn't know up front whether to output to a file
or to std::cout
.)
EDIT:
And yet another correction: the non-const version of rdbuf
calls clear()
,
so you don't have to. (I knew I'd done this without calling clear()
, but
when I saw that init
set badbit
...)
Anyhow: the summary is: it's usually preferrable to pass a pointer to a valid
streambuf to the constructor of std::ostream
, but if you can't, it's
perfectly valid to pass a null pointer, and set a valid pointer later using
rdbuf()
. And the answers which say otherwise are simply wrong.
ostream
to do? – Appointstd::cout
orstd::cerr
? be just like a stream for the output ? – Gildastd::cout
more like "the terminal" than a stream, If I just output everything to std::cout or std::cerr, than I have nothing left to analyze and everything is scattered in 2 buffers – Gildaint
s with the same address, that you use separately! No one would be able to trust a stream if some other part of the program could write to the exact same place whenever it wants. – Billiardsstd::ostream
if you want to but you can't use the default construct. You'd need to pass in a pointer to a stream buffer (std::streambuf*
) which can be null. For the streams to do anything, they need a stream buffer, however, which deals with sending the characters somewhere, e.g., astd::filebuf
sends them to a file, astd::stringbuf
sends them to a string, and user-defined stream buffers can send them wherever you wants them to send characters to, e.g., a GUI window or some area in memory. – Stevens