競技プログラミングでC++を使うときに、入出力を高速化する目的でおまじないのように書かれる
ios_base::sync_with_stdio(false); cin.tie(0);
の意味、実はよくわかっていなかったので c++ - Significance of ios_base::sync_with_stdio(false); cin.tie(NULL); - Stack Overflow を主に参考として調べてみました。
sync_with_stdio(false);
C++の標準入出力ストリームがCの入出力と同期しないようにします。代償として、 std::cin
と scanf()
を混ぜたり std::cout
と printf()
を混ぜたりすると破滅するようになります。
std::cin
とscanf()
を混ぜて入力がおかしくなる例を示します。まず以下のようなテキストファイルを用意します。
100 0 1 2 3 (略) 98 99
これを、以下のようにstd::ios::sync_with_stdio(false);
した上で、std::cin
とscanf()
で交互に数値を読み込みます。
#include <iostream> #include <cstdio> #include <vector> int main(void) { // C++の標準入出力ストリームがCの入出力と同期しないようにする std::ios::sync_with_stdio(false); int N; std::cin >> N; // 標準入力からcinとscanfで交互に数字を読む std::vector<int> arr(N); for(int n = 0; n < N; ++n) { if (n % 2) std::cin >> arr[n]; else scanf("%d", &arr[n]); } // 読み取った結果を表示 for(int n = 0; n < N; ++n) { std::cout << arr[n] << " "; } std::cout << std::endl; return 0; }
出力例は以下です。正しく数値を読み込めていないことがわかります。
0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 17 0 18 0 19 0 20 0 21 0 22 0 23 0 24 0 25 0 26 0 27 0 28 0 29 0 30 0 31 0 32 0 33 0 34 0 35 0 36 0 37 0 38 0 39 0 40 0 41 0 42 0 43 0 44 0 45 0 46 0 47 0 48 0 49
コードは https://ideone.com/u6TBWZ で実行を試すことができます。
cin.tie(0)
std::cin
とstd::cout
との結合を解きます。例えば、std::cout
で出力を要求する文字が全部出力される前に、std::cin
による入力待ち状態になることがありえるようになります。
#include <iostream> int main(void) { std::ios::sync_with_stdio(false); std::cin.tie(0); int n; for(int rep = 0; rep < 3; ++rep) { std::cout << "Input number: "; std::cin >> n; std::cout << n << " is given." << std::endl; } return 0; }
実行例は以下です。Input number:
が表示される前に数値の入力が要求されてしまいました。
$ ./a.exe 100 Input number: 100 is given. 200 Input number: 200 is given. 300 Input number: 300 is given.
std::cout << "Input number: " << std::flush;
とすればこの問題は解決可能です。