Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);
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.
Why does moving around ios_base::sync_with_stdio(false), cin.tie(NULL) result in a memory error?
From [ios.members.static]/2:
Effects: If any input or output operation has occurred using the standard streams prior to the call, the effect is implementation-defined. Otherwise, called with a
false
argument, it allows the standard streams to operate independently of the standard C streams.
Furthermore, the cppreference page notes that
If this function is called after I/O has occurred on the standard stream, the behavior is implementation-defined: implementations range from no effect to destroying the read buffer.
I'm not entirely sure what exactly happened in your case. Reading the source of libstdc++ (e.g., here), which I assume is the standard library being used, it seems that it clears the buffers. This means that it's possible that some input you were waiting for was buffered, and your program either started reading from a strange spot or the reads just failed entirely. But the precise details and why that would have caused an out of memory error is beyond me.
(It's also worth noting that the fact you're calling it in a loop doesn't seem to be the problem in this implementation, as libstdc++ only clears the buffers if you're already unsynchronised with stdio.)
How do I interpret this behavior of ios_base::sync_with_stdio(false); cin.tie(NULL);?
The thing you're not really understanding is what it means to synchronize with things, as well as what standard input and standard output really are.
Standard Input and Standard Output are global resources for your process. Each process has one Standard Input and one Standard Output. cin
represents a single way of reading from Standard Input. But scanf
is another way of reading from it.
Standard Input is global. So if one method of reading data reads something, then another one comes along and tries to read stuff, well the stuff the second one tried to read may not be there anymore. Here's an example of how that might happen.
The statement cin >> test;
will read something from standard input. How much something? Well, it will read at least enough to get a single long
type. But cin
is perfectly capable of reading much more than that. Typically, cin
will read data based on an internal buffer size.
Currently, your initial input is just 2 <return>
. However, it doesn't have to be. It could have been 2 2 2 2 2 10 <return>
. cin >> test;
will still only read a single integer. The rest will be unread input, which will be processed by the next cin
read command.
However, will that unread input actually still be in the global Standard Input? Probably not; cin
will likely read all of that data and shove it into an internal buffer. Once that happens, Standard Input contains nothing. Oh yes, using cin
will process the rest of the 2 2 2 2 10
input.
But using scanf
will not. Why? Because it doesn't know about cin
's internal buffer. It only reads from Standard Input. And the same goes for scanf
. It can have its own internal buffer of unread input, and cin
can't read that.
Well, not unless you synchronize the two systems. That is exactly what sync_with_stdio
is for: when it is set to true
(as it defaults to), operations on the standard streams will work between the two systems. cin
can read some characters, and scanf
can read some others, and neither will miss anything.
If however you do not synchronize them, then you shouldn't try to use both systems in the same application. To do so runs the risk of input going missing, or output not appearing in the right order.
The behavior of cin.tie
is exactly what the answer you linked to says: it ensures that stuff written to Standard Output will be displayed to the user before any attempts to read from Standard Input take place.
However, this only applies to cin
and cout
. scanf
does not necessarily participate in such tying behavior (whether synchronization is active or not). As such, it is undefined if the cout
statements will display anything to Standard Output before the scanf
statements start reading from Standard Input.
So cin.tie
does not apply to you.
std::ios_base::sync_with_stdio(false), advantages, disadvantages?
sync_with_stdio is a static
function.
so
std::cout.sync_with_stdio(false);
is in fact
std::cout, std::ios_base::sync_with_stdio(false);
Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);
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.
Why ios::sync_with_studio(0) and cin.tie(0); doesn't work with strings in C++
That's the way it is. You need to make sure that you're writing the names correctly. You can always take a look at https://en.cppreference.com/w/.
But in this case, check this: std::ios_base::sync_with_stdio
Also keep in mind that if set to false, the C++ standard stream objects such as cout
, clog
, cerr
, wcout
, etc. will not be synchronized and you might see unexpectedly interleaved output if you mix them.
Related Topics
How to Link to a Library With Code::Blocks
How to Convert an Enum Type Variable to a String
How to Emulate C Array Initialization "Int Arr[] = { E1, E2, E3, ... }" Behaviour With Std::Array
How Are Virtual Functions and Vtable Implemented
What Is the Advantage of Using Forwarding References in Range-Based For Loops
Is "For(;;)" Faster Than "While (True)"? If Not, Why Do People Use It
Reinterpret_Cast Creating a Trivially Default-Constructible Object
What Is the Meaning of Prepended Double Colon "::"
Forward Declaration of Nested Types/Classes in C++
What Should Go into an .H File
Cmake Error At Cmakelists.Txt:30 (Project): No Cmake_C_Compiler Could Be Found
C/C++ With Gcc: Statically Add Resource Files to Executable/Library
Difference Between 'New Operator' and 'Operator New'
Is "Argv[0] = Name-Of-Executable" an Accepted Standard or Just a Common Convention