Is Std::Cout Buffered

Is std::cout buffered?

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.

Usage of output stream buffer in context to std::cout and std::endl

No, your understanding is not correct. "Terminal emulators" are not involved, at least not directly.

The output buffer lives within the stream object itself (std::cout in this case). There are three possible ways this buffer is used, depending on the buffering policy of the stream:

  • Block buffered: Output is stored in the buffer first. When the buffer is full, it is "flushed", i.e. its contents are written to the underlying (OS specific) output channel and the buffer is emptied.

  • Line buffered: Works like block buffered, but the buffer is also flushed whenever a newline ('\n') is written to it.

  • Unbuffered: The output buffer is not used. All output is written immediately.

When you open a file, the stream starts out being block buffered. std::cerr is unbuffered. std::cout is line buffered if output goes to a terminal and block buffered otherwise.

std::flush flushes the output buffer immediately (if there is any).

As for how data is actually written, the details depend on your operating system. On unix systems, there is a system call called write (a "system call" is a request to the operating system to do something). System calls are typically slower than normal function calls; the output buffer is a performance optimization because you don't want to call write for every single character of output. Collecting output internally until you have a bigger batch of text to write means fewer calls to write, which means better overall performance.

As for your specific questions:

  1. No, terminal emulators are not relevant.

  2. The OS.

  3. The buffer is in the stream object, not the terminal emulator. Increasing the buffer size stops giving you any performance benefits after some point. Your program will usually spend most of its time calculating results and doing things other than writing text to std::cout.

What does this mean: 'std::cout' is buffered

Here's a related post:
Is std::cout buffered?

And here's an article that talks about it in more detail:
https://www.programmingincpp.com/flush-the-output-stream-buffer.html

How to prevent `std::cin` or `\n` from flushing the buffer of `std::cout`?

You could write to your own std::stringstream buffer, and then output that to std::cout when you're ready.

MWE:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>

using std::cin;
using std::cout;
using std::istream;
using std::runtime_error;
using std::stringstream;
using std::vector;

static auto get_int(istream& in) -> int {
int n;
if (!(in >> n)) {
throw runtime_error("bad input");
}
return n;
}

int main() {
auto ss = stringstream();
auto v = vector<int>();
auto size = get_int(cin);

while(size--) {
auto n1 = get_int(cin);

if (n1 == 0) {
auto n2 = get_int(cin);
v.push_back(n2);
} else if (n1 == 1) {
auto n2 = get_int(cin);
ss << v[n2] << '\n';
} else if (n1 == 2) {
v.pop_back();
}
}

cout << ss.str();
}

How the buffer of cout work?

You are mixing a lot of things. To date:

  • Implementation details of cout
  • Chained calls
  • Calling conventions

Try to read up on them separately. And don't think about all of them in one go.

printf("i=%d i++=%d i--=%d\n" , i , i++ ,i-- );

The above line invokes undefined behavior. Read the FAQ 3.2. Note, what you observe is a side-effect of the function's calling convention and the way parameters are passed in the stack by a particular implementation (i.e. yours). This is not guaranteed to be the same if you were working on other machines.

I think you are confusing the order of function calls with buffering. When you have a cout statement followed by multiple insertions << you are actually invoking multiple function calls, one after the other. So, if you were to write:

cout << 42 << 0;

It really means: You call,

cout = operator<<(cout, 42)

and then use the return in another call to the same operator as:

cout = operator<<(cout, 0)

What you have tested by the above will not tell you anything cout's internal representation. I suggest you take a look at the header files to know more.

How to make a simple C++ program in which std::cout is not flushed

This is not standard c++, but in POSIX, you can send a "kill" signal to kill the running process. This will stop the execution without cleanup such as flushing buffers.

Edit: I realized that signals are not only POSIX but actually part of C standard library (and included in the C++ standard library).

#include <csignal>
// ...
std::cout << "Don't write me to the console!";
std::raise(SIGKILL);


Related Topics



Leave a reply



Submit