c++bufferstd

Why is the output buffer still flushed immediately instead of waiting 10 seconds for it to display


According to the usage of cout object, the content will be stored in the output buffer first till the trigger condition happens or the program ends.

Then the output buffer is flushed.

Finally, the terminal displays the content.

But it displays immediately.

#include <iostream>
#include <windows.h>

int main() {
    std::cout << "Hello, World!";
    Sleep(10000);
    return 0;
}

How to reflect the buffer effect of cout method on the output stream?
Or it concerns with the operating system?


Solution

  • In general, std::cout is not buffered by default: as long as sync_with_stdio is active, every byte written to std::cout's buffer is immediately pushed to stdout's buffer.

    stdout is line-buffered by default in POSIX, so if you run the above program using gcc on linux (with C++ sleep instead of Windows Sleep), you will not observe the output until after the pause.

    Based on "Sleep(5000);" however, this is using Windows. There, C I/O streams are not buffered. You can observe that by replacing std::cout << "test"; with printf("test");. The output still appears immediately.

    You can still make Windows delay the output, if you enable buffering on stdout:

    #include <iostream>
    #include <cstdio>
    #include <windows.h>
    
    int main()
    {
        char buf[BUFSIZ];
        std::setbuf(stdout, buf);
        std::cout << "test";
        // std::fflush(stdout); // <- uncomment to see the text before the pause
        Sleep(5000);
        std::fflush(stdout);
        std::setbuf(stdout, NULL); // don't let the stream outlive the buffer
    }
    

    That demo won't let you observe the effect of std::flush though, since flush only moves cout's buffer (which it doesn't even have by default) into stdout's buffer, where the output sits until flushed using std::fflush or implicit means.

    To obseve std::flush, give std::cout its own buffer and disconnect it from C I/O streams:

    #include <iostream>
    #include <windows.h>
    
    int main()
    {
        char buf[BUFSIZ];
        std::ios::sync_with_stdio(false);
        std::cout.rdbuf()->pubsetbuf(buf, sizeof buf);
        std::cout << "test";
        //std::cout << std::flush; // <- uncomment to obseve the output before the pause
        Sleep(5000);
        std::cout << std::flush;
        std::cout.rdbuf()->pubsetbuf(nullptr, 0); // don't let the stream outlive the buffer
    }