Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);
Asked Answered
N

5

320

What is the significance of including

ios_base::sync_with_stdio(false);
cin.tie(NULL);

in C++ programs?

In my tests, it speeds up the execution time, but is there a test case I should be worried about by including this?

Do the 2 statements always have to be together, or is the first one sufficient, i.e., ignoring cin.tie(NULL)?

Also, is it permissible to use simultaneous C and C++ commands if its value has been set to false?

https://www.codechef.com/viewsolution/7316085

The above code worked fine, until I used scanf/printf in a C++ program with the value as true. In this case, it gave a segmentation fault. What could be the possible explanation for this?

Nita answered 1/7, 2015 at 13:12 Comment(1)
You actually used that with false . Your code says so???Micmac
L
483

The two calls have different meanings that have nothing to do with performance; the fact that it speeds up the execution time is (or might be) just a side effect. You should understand what each of them does and not blindly include them in every program because they look like an optimization.

ios_base::sync_with_stdio(false);

This disables the synchronization between the C and C++ standard streams. By default, all standard streams are synchronized, which in practice allows you to mix C- and C++-style I/O and get sensible and expected results. If you disable the synchronization, then C++ streams are allowed to have their own independent buffers, which makes mixing C- and C++-style I/O an adventure.

Also keep in mind that synchronized C++ streams are thread-safe (output from different threads may interleave, but you get no data races).

cin.tie(NULL);

This unties cin from cout. Tied streams ensure that one stream is flushed automatically before each I/O operation on the other stream.

By default cin is tied to cout to ensure a sensible user interaction. For example:

std::cout << "Enter name:";
std::cin >> name;

If cin and cout are tied, you can expect the output to be flushed (i.e., visible on the console) before the program prompts input from the user. If you untie the streams, the program might block waiting for the user to enter their name but the "Enter name" message is not yet visible (because cout is buffered by default, output is flushed/displayed on the console only on demand or when the buffer is full).

So if you untie cin from cout, you must make sure to flush cout manually every time you want to display something before expecting input on cin.

In conclusion, know what each of them does, understand the consequences, and then decide if you really want or need the possible side effect of speed improvement.

Lauter answered 1/7, 2015 at 15:22 Comment(6)
When you say "you must make sure to flush cout manually every time you want to display something before expecting input on cin", that can be as simple as appending "... << std::flush" or "... << std::endl" to the end of every line that begins "std::cout << ...", right?Joselyn
Yes, it is as simple as that, but be careful with "the end of every line" part. cout is buffered for a reason, if you flush it too often, when you don't actually need it, you might see a performance hit.Lauter
@Lauter is there something equivalent to the tie() functionality in C for scanf, printf?Treadwell
@iajnr No, not directly. In C, you can either flush manually before scanf(), disable buffering completely or switch to line buffering (which should flush after newline or when input is read from stdin - see linux.die.net/man/3/setlinebuf ).Lauter
At leetcode, it significantly improves runtime, maybe these competitive websites do something special for input tests.Myra
"Also keep in mind that synchronized C++ streams are thread-safe" so is there an effect of sync_with_stdio(false) on this thread-safety? Only when mixing C and C++ I/O perhaps?Secretory
E
46

This is to synchronize IOs from C and C++ world. If you synchronize, then you have a guaranty that the orders of all IOs is exactly what you expect. In general, the problem is the buffering of IOs that causes the problem, synchronizing let both worlds to share the same buffers. For example cout << "Hello"; printf("World"); cout << "Ciao";; without synchronization you'll never know if you'll get HelloCiaoWorld or HelloWorldCiao or WorldHelloCiao...

tie lets you have the guaranty that IOs channels in C++ world are tied one to each other, which means for example that every output have been flushed before inputs occurs (think about cout << "What's your name ?"; cin >> name;).

You can always mix C or C++ IOs, but if you want some reasonable behavior you must synchronize both worlds. Beware that in general it is not recommended to mix them, if you program in C use C stdio, and if you program in C++ use streams. But you may want to mix existing C libraries into C++ code, and in such a case it is needed to synchronize both.

Eduard answered 1/7, 2015 at 14:40 Comment(2)
Even without syncronization, different calls to cout << cannot change order so CiaoHelloWorld is not possible for your example case. Syncronization is strictly about different buffering methods.Electrocute
i don't even know if it is true, but I upvoted because of explanationDogcart
M
13

It's just common stuff for making cin input work faster.

For a quick explanation: the first line turns off buffer synchronization between the cin stream and C-style stdio tools (like scanf or gets) — so cin works faster, but you can't use it simultaneously with stdio tools.

The second line unties cin from cout — by default the cout buffer flushes each time when you read something from cin. And that may be slow when you repeatedly read something small then write something small many times. So the line turns off this synchronization (by literally tying cin to null instead of cout).

Magnetograph answered 13/6, 2020 at 17:4 Comment(0)
M
6

Using ios_base::sync_with_stdio(false); is sufficient to decouple the C and C++ streams. You can find a discussion of this in Standard C++ IOStreams and Locales, by Langer and Kreft. They note that how this works is implementation-defined.

The cin.tie(NULL) call seems to be requesting a decoupling between the activities on cin and cout. I can't explain why using this with the other optimization should cause a crash. As noted, the link you supplied is bad, so no speculation here.

Mayest answered 1/7, 2015 at 14:40 Comment(0)
U
4

There are lots of great answers. I just want to add a small note about decoupling the stream.

cin.tie(NULL);

I have faced an issue while decoupling the stream with the CodeChef platform. When I submitted my code, the platform response was "Wrong Answer" but after tying the stream and testing the submission. It worked.

So, If anyone wants to untie the stream, the output stream must be flushed.

Underhung answered 16/8, 2020 at 11:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.