-
ios_base::sync_with_stdio(false); cin.tie(NULL);알고리즘과 언어/c++ 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
'알고리즘과 언어 > c++' 카테고리의 다른 글
C++) 백준 1780 종이의 개수 (0) 2022.02.08 C++) 원하는 자리수 까지 출력하기 (반올림, 올림, 내림) (0) 2022.02.07 정규표현식 <regex> (0) 2021.09.20 최대값, 최소값 max_element min_element (프로그래머스 프린터) (0) 2021.08.19 [hash, vector] 프로그래머스 베스트 앨범 (0) 2021.08.18