Unbuffered output with cout
You can set the std::ios_base::unitbuf
flag to flush output after each output operation either by calling std::ios_base::setf
:
std::cout.setf(std::ios::unitbuf);
or using the std::unitbuf
manipulator:
std::cout << std::unitbuf;
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:
No, terminal emulators are not relevant.
The OS.
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
.
Is std::cout buffered?
Yes, it's buffered:
C++11 27.4.2 [narrow.stream.objects]/3
: The objectcout
controls output to a stream buffer associated with the objectstdout
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.
Does setbuf() affect cout?
By default, iostreams and stdio are synchronised. Reference.
This doesn't mean that manually adjusting the stdio buffering is a good idea, though! You may wish to utilise std::endl
or std::flush
(from <ostream>
), which may help you. e.g.,
std::cout << "Hello, world!" << std::endl;
or
std::cout << "Hello, world!\n" << std::flush;
Both of these do the same thing. (std::endl
= print endline, then flush.)
Buffered and unbuffered stream
Your book doesn't seem very helpful.
1) The output streams send their bytes to a std::streambuf
, which may
contain a buffer; the std::filebuf
(derived from streambuf
) used by
and std::ofstream
will generally be buffered. That means that when
you output a character, it isn't necessarily output immediately; it will
be written to a buffer, and output to the OS only when the buffer is
full, or you explicitly request it in some way, generally by callingflush()
on the stream (directly, or indirectly, by using std::endl
).
This can vary, however; output to std::cout
is synchronized withstdout
, and most implementations will more or less follow the rules ofstdout
for std::cout
, changing the buffering strategy if the output
is going to an interactive device.
At any rate, if you're unsure, and you want to be sure that the output
really does leave your program, just add a call to flush.
2) Your book is wrong here.
One of the buffering strategies is unitbuf
; this is a flag in thestd::ostream
which you can set or reset (std::ios_base::set()
andstd::ios_base::unset()
—std::ios_base
is a base class ofstd::ostream
, so you can call these functions on an std::ostream
object). When unitbuf
is set, std::ostream
adds a call to flush()
to the end of every output function, so when you write:
std::cerr << "hello, world";
the stream will be flushed after all of the characters in the string
are output, provided unitbuf
is set. On start-up, unitbuf
is set
for std::cerr
; by default, it is not set on any other file. But you
are free to set or unset it as you wish. I would recommend against
unsetting it on std::cerr
, but if std::cout
is outputting to an
interactive device, it makes a lot of sense to set it there.
Note that all that is in question here is the buffer in the streambuf
.
Typically, the OS also buffers. All flushing the buffer does is
transfer the characters to the OS; this fact means that you cannot useofstream
directly when transactional integrity is required.
3) When you input to a string or a character buffer using >>
, thestd::istream
first skips leading white space, and then inputs up to
but not including the next white space. In the formal terms of the
standard, it "extracts" the characters from the stream, so that they
will not be seen again (unless you seek, if the stream supports it).
The next input will pickup where ever the previous left off. Whether
the following characters are in a buffer, or still on disk, is really
irrelevant.
Note that the buffering of input is somewhat complex, in that it occurs
at several different levels, and at the OS level, it takes different
forms depending on the device. Typically, the OS will buffer a file by
sectors, often reading several sectors in advance. The OS will always
return as many characters as were demanded, unless it encounters end of
file. Most OSs will buffer a keyboard by line: not returning from a
read request until a complete line has been entered, and never returning
characters beyond the end of the current line in a read request.
In the same manner as std::ostream
uses a streambuf
for output,std::istream
uses one to get each individual character. In the case
of std::cin
, it will normally be a filebuf
; when the istream
requests a character, the filebuf
will return one from its buffer if
it has one; if it doesn't, it will attempt to refill the buffer,
requesting e.g. 512 (or whatever its buffer size is) characters from the
OS. Which will respond according to its buffering policy for the
device, as described above.
At any rate, if std::cin
is connected to the keyboard, and you've
typed "hello world"
, all of the characters you've typed will be read
by the stream eventually. (But if you're using >>
, there'll be a lot
of whitespace that you won't see.)
Related Topics
How to Make a C++ Struct Value-Initialize All Pod Member Variables
Very Simple Application Fails with "Multiple Target Patterns" from Eclipse
What Happens When a Function That Returns an Object Ends Without a Return Statement
Want to Efficiently Overcome Mismatch Between Key Types in a Map in Boost.Interprocess Shared Memory
Passing Constexpr Objects Around
Svm Classifier Based on Hog Features for "Object Detection" in Opencv
Getting the Size of a C++ Function
How to Not Wait for a System() Command to Finish? (In C)
Implementing a Std::Vector Like Container Without Undefined Behavior
How to Omit the Double-Braces for Std::Array in C++14
Boost::Asio + Std::Future - Access Violation After Closing Socket
What Happens When I Assign a Number Larger Than Int_Max to an Int