알고리즘과 언어/c++

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

nextcoder 2021. 11. 14. 02:35

 

주로 코딩 테스트를 C++로 풀었기 때문에 python과 같은 언어에 비해 시간 초과가 나지 않을 것이라 생각했다.

그렇게 백준에서 간단한 알고리즘을 돌리려 한 그 때.. time fail이 났고 위 구문을 추가하고, 또 다른 1가지를 바꿔주자 correct 가 되었다.

 

main 함수 안에 

ios_base::sync_with_stdio(false);    

cin.tie(NULL);

 

를 쓰는 것을 몇 번 본 적이 있었다.

단순히 입출력 시간을 단축해주는 것 정도로 생각했다.

찾아보고 자세히 알게된 점이 있어 기록하게 되었다.

 

 

 

1. ios_base::sync_with_stdio(false);

 

먼저, C++ <iostream> 표준 입출력은 C와 다르게 구현이 되어있다고 한다.

기본적으로 C++에서 입출력 작업을 할 때마다 C의 표준 입출력과 동기화되어 있도록 설정이 되어 있는데, 이 과정이 생각보다 꽤 느리다고.

 

ios_base::sync_with_stdio가 이 동기화를 말하는 것이고, 동기화를 풀어줌으로써 속도를 올릴 수 있다.

그러나 위와 같이 동기화를 풀어주게 되면 싱글 쓰레드 환경에서는 문제가 되지 않지만 멀티 쓰레드 환경에서는 출력 순서를 보장할 수 없다고 한다.

 

(다행히 코딩 테스트에서는 싱글 쓰레드만 사용한다. 실무에선 쓰지 말라고 한다. 실무에선 ios_base::sync_with_stdio(false) 를 쓰지 말고 속도를 올리려면 C입출력을 쓰라고 한다.)

 

또한, 버퍼가 분리되었기에 위 구문을 적은 후에 cin과 C의 scanf, gets, getchar 등을 같이 사용하거나,

cout과 C의 printf, puts, putchar를 같이 사용하면 안된다고 한다.

 

 

 

2. cin.tie(NULL);

cin과 cout간의 tie를 풀어주는 것. C++은 다른 입출력이 올 때, 기존의 입출력을 flush(비우기)한다.

예를 들면,

cout << "입력하시오";
cin >> num;

에서 num을 입력하기 전에 "입력하시오"가 나오는 것은, 입출력 전에 기존의 입출력을 비우기 때문이라고 한다.

이 tie를 풀어주게 되면, 콘솔에 "입력하시오"가 뜨지 않는다고 한다.

입력 전에 뭔가 띄우고 싶다면 cout 버퍼를 수동적으로 비워줘야 한다고 한다.

 

이 tie를 풀어줌으로써 시간을 많이 절감할 수 있다고 한다.

 

 

 

** 요약 **

ios_base::sync_with_stdio(false); 는 C 표준 입출력과의 동기화를 하지 않도록 설정하여 속도를 빠르게 올릴 수 있고,

cin.tie(NULL); cout.tie(NULL); 은 스트림을 untie 시켜서 자동적으로 입출력 버퍼를 비우지 않도록 설정함으로써 속도를 높인다.

 

 

 

추가적으로, 이 두가지를 쓰고도 시간 초과 문제가 해결이 안되었는데

 

그것은 endl 에 있었다. 

endl은 출력 문자를 출력할 뿐 아니라, 출력 버퍼도 비우기 함께 비우기 때문에 시간이 많이 걸림.

가능하면 cout << 출력할 아무거나 << '\n'; 를 사용하자 !

 

 

 

 

참고자료:

 

https://www.acmicpc.net/board/view/33074

https://jaimemin.tistory.com/1521

https://hegosumluxmundij.tistory.com/54