Is std::cout buffered?
Asked Answered
C

5

24

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?

Carrefour answered 17/11, 2014 at 15:19 Comment(1)
This has some info: https://mcmap.net/q/582311/-c-buffered-stream-ioWellstacked
O
25

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.

Okinawa answered 17/11, 2014 at 15:25 Comment(5)
I saw that. But if you read the next paragraph down. It says the same thing about std:cerr which is not buffered. So I was not convinced the word buffer is not being overloaded here. The object cerr controls output to a stream buffer associated with the object stderrCarrefour
@LokiAstari: cerr is also buffered. The difference is that it has unitbuf set, so it's automatically flushed after each line.Okinawa
(By "line" I meant "operation". Too late to fix the comment now.)Okinawa
Stream buffers don't actually have to do any buffering.Pinson
@Hurkyl: Indeed, if you want a fully pedantic answer, then there's a stream buffer object managing access to the underlying C stream in an unspecified way that may or may not involve activity that one might call "buffering".Okinawa
M
12

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 (i.e. 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.

Macromolecule answered 17/11, 2014 at 16:3 Comment(0)
T
10

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.

Twinkling answered 17/11, 2014 at 15:39 Comment(1)
From memory, this hasn't changed since C90, and corresponds to the requirements in the original Unix manuals for C. On the other hand, he was asking about C++, and C++ has different rules. (In particular, C++ doesn't have the concept of line buffered.)Macromolecule
P
2

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.

Palumbo answered 17/11, 2014 at 15:25 Comment(5)
You are confusing stdout and std::cout. The former is line-buffered for terminals and block-buffered otherwise.Nodababus
What I said is the same as Jerry Coffin and as written in the C99 standard.Palumbo
I do not think std::cout is mentioned in C99 standard.Nodababus
That is true. I'm sorry. But even so, I think that the standard for stdout is reflected in std::cout.Palumbo
@nighthawk702 There's no requirement that it be, as long as output to stdcout comes out in the right order, and obeys the rules specified in C.Macromolecule
I
2

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;
Impeachable answered 17/11, 2014 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.