问题
I understand that by default all stream IO supported by C++ is buffered.
This means that data to be output is put into a buffer till it is full and then sent to the output device, similarly for input, the data is read once the buffer is empty...all this is done so that number of expensive system calls could be minimized.
But how to verify this behavior in action. I mean consider the following code
int main()
{
cout << "Hello world\n";
return 0
}
Where does buffering come into picture here ? I know there is buffering happening, but how to explain it? The output is seen instantly on the screen, so what could be a code example to actually see buffered I/O in action ?
回答1:
Try the following program. sleep(1)
is used to introduce delay(1 second), I'm using linux, so sleep
works for me. If you can't make it work, try other ways to delay this program(for example, simple for
loop). You may also try increasing buffer size(uncomment commented lines of code) if you don't see any buffering effect.
On my OS(Linux 3.2.0
) and compiler(g++ 4.6.3
), this program prints "Portion1Portion2" then "Portion3Portion4" and then "Portion5". std::endl guaranteed to flush buffer, but as you can see, newline character also works this way for me.
#include <iostream>
#include <unistd.h>
using namespace std;
int main () {
// Try uncommenting following lines to increase buffer size
// char mybuf[1024];
// cout.rdbuf()->pubsetbuf(mybuf, 1024);
cout << "Portion1";
sleep(1);
cout << "Portion2\n";
sleep(1);
cout << "Portion3";
sleep(1);
cout << "Portion4" << endl;
sleep(1);
cout << "Portion5" << endl;
sleep(1);
cout << "Done!" << endl;
return 0;
}
回答2:
First, not all iostream is buffered; buffering is handled by the attached
streambuf
. In the case of filebuf
(used by ifstream
and
ofstream
), input will read as much as possible, up to the size of the
buffer, and output will flush the buffer on overflow, when an
explicit flush or close occurs, or when the object is destructed (which
implicitly calls close).
The case of cout
is a bit special, since it is never destructed nor
closes. There is a guarantee from the system that flush
will be
called on it at least once after exit
is called (which is what happens
when you return from main
). This means that any output before
returning from main will be flushed; if you're using cout
in
destructors of static objects, you still need an explicit flush to be
sure.
It's also possible to tie
an output stream to an input stream; cout
is tied to cin
by default. In this case, any attempt to input from
the tied stream will flush the output.
The usual convention is to just use std::endl
instead of simply
outputting '\n'
; std::endl
outputs a '\n'
and then flushes the
stream. For streams where it is very important for all output to appear
promptly, there is a unitbuf
flag which can be set, which means that
the stream will be flushed at the end of each <<
operator.
(std::cerr
has this set by default.)
Finally, if you want to see the effect of buffering, put something like
sleep(10)
after your output. If it output appears immediately, it has been
flushed; if it doesn't it has been buffered, and the flush occured
implicitly after the sleep
.
回答3:
Try the following code:
int main()
{
for( int i =0 ; i < 10; i ++ )
{
cout << i << " ";
cerr << i << " ";
}
}
The buffered output is usually flushed with the destruction of the stream object, so the code above will print (not always, ofc, but it does for me with gcc 4.6.3)
0 1 2 3..9
0 1 2 3..9
instead of
0 0 1 1 2 2 3 3 .... 9 9
Because the unbuffered cerr
is printed right away (first sequence) , and buffered cout
is printed in the end of main()
.
来源:https://stackoverflow.com/questions/11392511/c-buffered-stream-io