Just reading an old but interesting article by "Scott Meyers"
http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf
Basically it is about preferring to use '\n'
over std::endl
(which I agree with and have used the same augment for years).
BUT the last section indicates this was not included in his book because the whole thing was rendered moot because of two points:
std::cout
was not buffered.- The state of
ios::unitbuf
on std::cout is not explicitly defined (thus implementation dependent).
I did a quick look but could not find an explicit standards reference for 1
was true. Is std::cout
unbuffered contrary to what I have always understood?
From what I read form here, cout is usually buffered, but when it detects that it prints to an interactive environment, like the console, it falls back to unbuffered.
So if you redirect the output (using the '>' in UNIX) then the buffered behavior kicks in.
More details in the linked post.
First, there is no requirement that
std::cout
(or evenstd::cerr
) be unbuffered. The only requirement is thatstd::cerr
havestd::basic_ios::unitbuf
set (so that it will flush at the end of each output function:<<
or a non-formatted output function). On the other hand, unless you've calledstd::basic_ios::sync_with_stdio(false)
, outputting to the C++ streams and outputting to the corresponding C streams (i.e.std::cout
andstdout
) must have the same effects. In theory, this can be done in several ways:stdout
functions can forward to those ofstd::cout
,std::cout
output can forward tostdout
, or they can share some common buffer implementation under the hood. In practice, practically all implementations havestd::cout
forwarding tostdout
.C specifies that
stderr
not be fully buffered, and thatstdout
may be fully buffered only if it can be determined not to refer to an interactive device (for some implementation defined meaning of "interactive device"). Typically,stdout
will be line buffered (a concept which doesn't exist in iostream), andstderr
will be unbuffered, but that's not guaranteed by the C standard (and may not be true today—the last time I really looked was over twenty years ago). Anyway, an implementation which just forwards tostdout
will follow the rules of the C implementation it forwards to, and one that doesnt' still needs to take some steps to ensure that output tostd::cout
andstdout
comes out in the right order, and thatstdout
behaves "as if" it obeyed the C rules.If you're worried about performance, then you might want to run some trials. Try measuring the time it takes to output to an
std::ofstream
you've opened yourself, versus the time it takes to output tostd::cout
(both with and without having calledsync_with_stdio
), with the output redirected. The differences should be interesting.Yes, it's buffered:
The article refers to a 1995 draft version of what became the C++98 standard. I've no idea whether or not that might have said something different.
As for point 2,
unitbuf
is initially false on all streams (specified by the post-conditions of thebasic_ios
constructor), except forcerr
andwcerr
which explicitly specify otherwise. Again, that may well be different in the ancient draft being referred to.The C++ standard defines all input and output as being "as if" all reading and writing ultimately happened via reads and writes of C streams ([iostream.objects.overview]):
For the behavior of the standard C streams attached to those objects, we have to refer to the C standard (§7.19.3):
Here I'm quoting from the C99 standard, but I'm reasonably certain that (modulo changes in section numbering) the same is in all versions of the C standard.
According to this page -- http://www.programmingincpp.com/flush-the-output-stream-buffer.html -- std::cout is buffered. I have had something fail to print because a program crash happened after the cout << ... statement but before it was flushed: