简体   繁体   中英

Is std::cout buffered?

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:

  1. std::cout was not buffered.
  2. 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?

Yes, it's buffered:

C++11 27.4.2 [narrow.stream.objects]/3 : The object cout controls output to a stream buffer associated with the object stdout

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 the basic_ios constructor), except for cerr and wcerr which explicitly specify otherwise. Again, that may well be different in the ancient draft being referred to.

First, there is no requirement that std::cout (or even std::cerr ) be unbuffered. The only requirement is that std::cerr have std::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 called std::basic_ios::sync_with_stdio(false) , outputting to the C++ streams and outputting to the corresponding C streams (ie std::cout and stdout ) must have the same effects. In theory, this can be done in several ways: stdout functions can forward to those of std::cout , std::cout output can forward to stdout , or they can share some common buffer implementation under the hood. In practice, practically all implementations have std::cout forwarding to stdout .

C specifies that stderr not be fully buffered, and that stdout 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), and stderr 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 to stdout 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 to std::cout and stdout comes out in the right order, and that stdout 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 to std::cout (both with and without having called sync_with_stdio ), with the output redirected. The differences should be interesting.

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]):

The header declares objects that associate objects with the standard C streams provided for by the functions declared in (27.9.2), and includes all the headers necessary to use these objects.

For the behavior of the standard C streams attached to those objects, we have to refer to the C standard (§7.19.3):

At program startup, three text streams are predefined and need not be opened explicitly — standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output). As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

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.

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.

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:

cout << "My error or flag message, but it's not flushed, so I never see it";

//system crash!

cout << endl;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM