What's std::ios::sync_with_stdio(false) and std::cin.tie(nullptr)?
800 Words | Read in about 4 Min | View times
Overview
You may often see the following calls std::ios::sync_with_stdio(false)
and std::cin.tie(nullptr)
in some online judge system, such as leetcode, poj, etc. Someone would tell you that these codes are usually used to speed up the execution time. But what is the exact meanings for these codes?
1static auto _ = []() {
2 std::ios::sync_with_stdio(false);
3 std::cin.tie(nullptr);
4 return nullptr;
5}();
These two calls have different meanings that have nonthing to do with performance. The fact that it speeds up code execution time is just a side effect.
Decoupling C and C++ streams
Function
1static bool std::ios::sync_with_stdio(bool sync = true);
Sets whether the standard C++ streams are synchronized to the standard C streams after each input/output operation.
The standard C++ streams are: std::cin
, std::cout
, std::cerr
, std::clog
, std::wcin
, std::wcout
, std::wcerr
and std::wclog
.
The standard C streams are: stdin
, stdout
and stderr
.
By default, sync_with_stdio()
has default value true
, which means all standard streams are synchronized between C and C++ standard streams. In practice, it allows you to mix C and C++ style I/O and get expected results.
Example 1
1#include <iostream>
2#include <cstdio>
3
4int main() {
5 std::cout << "a\n";
6 std::printf("b\n");
7 std::cout << "c\n";
8 return 0;
9}
10
In general, the result for the above example is:
1a
2b
3c
This is the default behavior in C++. The C stream stdout
and C++ stream std::out
are synchronized, they share the same I/O buffer. In fact, the C++ streams are unbuffered, and each I/O operaction on C++ streams is immediately applied to the corresponding C streams buffer. So it will result the correct order for all output.
Now let’s make some change.
Example 2
1#include <iostream>
2#include <cstdio>
3
4int main() {
5 std::cout << "a\n";
6 std::printf("b\n");
7 std::cout << "c\n";
8 return 0;
9}
10
11static auto _ = []() {
12 std::ios::sync_with_stdio(false);
13 return nullptr;
14}();
You may get a possible output like this:
1b
2a
3c
Woops! The output result is no longer abc.
After set false
to sync_with_stdio
, the C streams and C++ streams are no longer synchronized. In fact, they will maintain indepedent buffers for their own, each I/O operation on C++ streams will not be applied to the corresponding C stream buffer now, which may be considerably faster than in some cases.
In addition, I’m not using std::endl
to break line for std::cout
, beacuse std::endl
will flush the I/O buffer immediately which you won’t see what happen between the C and C++ streams synchronization.
Decoupling input and output streams
Function
1ostream* tie (ostream* tiestr);
The tied stream is an output stream object which is flushed before each I/O operation in this stream object.
By default, the standard stream std::cin
and std::cerr
are tied to std::cout
, and std::wcin
and std::wcerr
are tied to std::wcout
to ensure a sensible user interaction.
Example 1
1#include <iostream>
2#include <string>
3
4int main() {
5 std::string name;
6 std::cout << "What's your name:";
7 std::cin >> name;
8 std::cout << "Your name is " << name << std::endl;
9 return 0;
10}
In gernal, the result for the above code is:
1What's your name:
After type my name:
1What's your name:zhxilin
2Your name is zhxilin
The standard input stream std::cin
is tied to the output stream std::cout
by default, which means before type my name to the input stream, the output stream buffer is flushed to the console. So you can see the sentence What's your name
before any typing.
Now let’s make some change.
Example 2
1#include <iostream>
2#include <string>
3
4int main() {
5 std::string name;
6 std::cout << "What's your name:";
7 std::cin >> name;
8 std::cout << "Your name is " << name << std::endl;
9 return 0;
10}
11
12static auto _ = []() {
13 std::ios::sync_with_stdio(false);
14 std::cin.tie(nullptr);
15 return nullptr;
16}();
You won’t see the sentance What's your name
before any typing now. But after type my name, the result is:
1zhxilin
2What's your name:Your name is zhxilin
Therefore, if std::cin
and std::cout
are tied, you can expect the ouput to be flushed before the program prompts input for user. In this case, the output stream should be manually flushed or until the buffer is fulled. As for the side effect, some codes will speed up when execution for untied and non-synchronized streams.
Conclusion
- Using
std::ios::sync_with_stdio(false)
is sufficient to decouple C and C++ streams. - Using
std::cin.tie(nullptr)
is sufficient to decouplestd::cin
andstd::cout
. - Speeding up I/O operation effeciency is only some side effects for calling these functions in some ACM-case.
References
- https://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio
- https://en.cppreference.com/w/cpp/io/basic_ios/tie