우리는 알고리즘 문제를 풀이할 때 시간 초과가 발생하는 경우 다음과 같은 코드를 작성하여 실행 속도를 줄이곤 한다.
ios_base::sync_with_stdio(false);
cin.tie(NULL);
왜 이 코드를 작성하게 되면 실행 속도를 줄일 수 있을지 알아보도록 하자.
이 두 줄의 코드는 사실 실행 속도와는 관련이 없는 코드라고 한다. 단순히 부수 작용으로 속도가 향상되는 것이지 항상 속도가 향상된다고 단정지을 수 없다. 따라서 우리는 이 두 줄의 코드가 실행 속도를 줄여준다고 생각하고 모든 코드에 추가하는 행동은 지양해야 한다.
cin과 cout은 scanf와 printf에 비해 속도가 느리다. 입출력 속도의 차이는 버퍼 때문인데, cin과 cout이 느린 이유는 C 라이브러리의 stdio 버퍼와 동기화하는 과정 때문이다.
ios_base::sync_with_stdio()
ios_base::sync_with_stdio() 구문은 C의 stdio와 C++의 iostream을 동기화하게 해준다.
괄호 안에 false 값을 넣게 되면, 동기화를 비활성화 할 수 있게 된다.
따라서 C++ 만의 독립적인 버퍼를 사용할 수 있게 되고, 실행 속도도 빨라지게 된다.
cin.tie(NULL);
cin.tie(NULL) 구문은 cout으로부터 cin을 분리해낸다. 기본적으로 cin과 cout은 묶여 있고 이 연결된 스트림을 사용하면 다른 스트림에서 각 I/O 작업을 수행하기 전에 한 스트림이 자동으로 플러시된다.
std::cout << "Enter Name : ";
std::cin >> name;
cin과 cout이 하나의 스트림으로 묶여 있다면 사용자로부터 입력을 요청하기 전에 출력이 플러시(즉, 콘솔에 표시)될 것으로 예상할 수 있다. 스트림을 풀면 프로그램에서 사용자가 이름을 입력하기를 기다리는 것을 차단할 수 있지만 "Enter Name : " 메시지는 아직 표시되지 않는다. (cout은 기본적으로 버퍼링되기 때문에 요청 시 또는 버퍼가 꽉 찾을 때만 콘솔에 플러시/표시된다.)
따라서 cout에서 cin을 풀 경우, cin에 무엇인가 입력하기 전에 무엇인가 표시하고 싶을 대마다 cout을 플러시하는 것을 확실히 해야 한다.
정리하자면, ios::base::sync_with_stido(false) 구문을 사용할 때는 scanf와 printf를 섞어 사용하지 않도록 주의하여 싱글 쓰레드 환경에서만 사용해야 한다. 하지만, 이 구문으로 속도를 줄이는 방식이 통하지 않는 경우도 있다고 한다. cin.tie(NULL) 구문의 경우 cout과 cin의 묶음을 풀어주게 되는데, 이를 통해 버퍼의 관리를 더욱 효율적으로 하게 되어 속도를 줄여준다고 예상한다.
* 해당 게시물은 https://jaimemin.tistory.com/1521, https://stackoverflow.com/questions/31162367/significance-of-ios-basesync-with-stdiofalse-cin-tienull, https://codenamejy.tistory.com/16, https://hegosumluxmundij.tistory.com/54 을 참고하여 작성되었음을 알립니다.
'Coding > C++' 카테고리의 다른 글
연산자 중복 - '숫자' + '객체' (0) | 2019.08.19 |
---|---|
명품 C++ Programming 6장 Open Challenge (0) | 2019.08.13 |