Why std::nounitbuf doesn't do anything on MSVC?

Viewed 214

I am writing a course on modern C++ and wanting to explain how the flush operations work, so I decided to disable the automatic flush in order to write to the buffer only when std::cout is destroyed.

For that, only one standard function exists and it is the manipulator std::nounitbuf.

However, this doesn't work on MSVC.

What surprises me the most is that the alternative in C, the setvbuf function, actually allows you to deactivate the automatic flush.
It bothers me a little because I want to teach C++ and not C.

Can anyone help me? thank you!

#include <iostream>
#include <thread>

int main()
{
    std::cout << std::nounitbuf; // doesn't work (output is two Hello World before the 5 seconds delay)
    //setvbuf(stdout, nullptr, _IOFBF, BUFSIZ); // work (output is one Hello World, then another one after the 5 seconds)

    std::cout << "Hello World" << std::endl;
    std::cout << "Hello World";

    std::this_thread::sleep_for(std::chrono::seconds{ 5 });
}
2 Answers

From: https://en.cppreference.com/w/cpp/io/manip/endl

In many implementations, standard output is line-buffered, and writing '\n' causes a flush anyway, unless std::ios::sync_with_stdio(false) was executed.

Try to remove std::endl and '\n' from the output and you will get the desired behavior. And as Marek said, std::nounitbuf is default setting for std::cout.

Why std::nounitbuf doesn't do anything?

Most probably because unitbuf flag is not set by default for standard cout stream. (Standard narrow.stream.objects requires it should be set only for cerr).

Can anyone help me?

C++ are synchronized (not buffered) with stdio streams. What you write std::cout << "something" goes straight to FILE* stdout. As it goes straight there, stdout buffering is all that matters.

Disable synchronization with stdio streams and try then. Read about std::ios::sync_with_stdio. The following works for me.

#include <iostream>
#include <thread>
int main() {
    std::ios::sync_with_stdio(false);

    std::cout << "Hello World" << std::endl;
    std::cout << "Hello World\n";

    std::this_thread::sleep_for(std::chrono::seconds{ 5 });
}
Related