C++ buffered stream IO

旧城冷巷雨未停 提交于 2019-12-01 08:34:34

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;
}

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.

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().

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!