C++로 코딩테스트를 풀 때 추가하는 구문의 목적

2022. 5. 3. 14:10TIL💡/Algorithms

C++로 알고리즘을 풀 때 실행 속도를 높이기 위해 아래와 같은 구문을 추가한다.

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

첫 번째 코드

ios_base::sync_with_stdio는 c의 stdio와 cpp의 iostream을 동기화시켜주는 역할을 한다.

이 때 iostream과 stdio의 버퍼를 모두 사용하기 때문에 delay가 발생한다.

 

ios_base::sync_with_stdio(false) 코드를 작성함으로써 동기화를 비활성화해준다.

이로 인해 C++(iostream)만의 독립적인 버퍼가 생성되어 C의 버퍼와 병행하여 사용할 수 없게 된다.

그러나 동기화를 하지 않기 때문에 실행속도는 빨라진다.

알고리즘 문제를 풀 때는 대부분 싱글 스레드이기 때문에 해당 코드를 추가해줘도 별다른 차이가 없다.

 

단점도 있다.

동기화된 C++ 버퍼의 경우 Thread-Safe하기 때문에 모든 I/O의 순서가 보장된다.

하지만 동기화를 비활성화할 경우, 멀티 스레드 환경에서는 출력 순서를 보장할 수 없게 된다.

그리고 버퍼가 분리되었기 때문에 iostream의 cin과 C의 scanf, gets, getchar 등을 같이 사용하면 안되고, 같은 논리로 iostream의 cout와 C의 printf, puts, putchar 등을 같이 사용하면 엉뚱한 결과가 나온다.

 

두 번째 코드

cin과 cout의 묶음을 푼다.

기본적으로 cin, cout는 묶여 있고, 묶여 있는 스트림은 한 스트림이 다른 스트림에서 I/O작업을 진행하기 전에 자동으로 버퍼를 비워준다.

 

ex)

cout << "이름을 입력하세요: ";
cin >> name;

위 경우 cin과 cout가 묶여있기 때문에 이름을 입력하기 전에 이름을 입력하세요: 구문이 먼저 출력된다.

하지만 cin.tie(null) 코드를 추가하면 cin과 cout의 묶음이 풀리면서 이름을 입력하세요: 구문이 출력되기 전에 먼저 이름을 입력받는 경우가 발생할 수 있다.

 

이는 cout이 기본적으로 버퍼에 추가되고 바로 비워지지 않기 때문이다. 출력 명령을 내리거나 버퍼가 가득 찼을 경우에만 버퍼를 비우고 출력하게 된다. 따라서 입력을 받기 전에 반드시 버퍼를 비워줘야 한다.

 

Wrap Up

위의 단점들은 싱글스레드 환경에서의 알고리즘 풀이에서 문제가 되지 않는다.

따라서 C의 입출력 코드를 사용하지 않는 이상 괜찮다.

입력과 출력을 여러 번 번갈아가면서 반복해야할 때 cin.tie(null)코드를 작성하면 성능을 높일 수 있다.

 

그리고 endl 구문을 통해 개행을 하게 되면 개행 문자 출력과 동시에 출력 버퍼를 비우기 때문에 delay가 발생한다.

따라서 실행속도를 높이기 위해 C 스타일의 개행문자인 \n 을 쓰는 것이 권장된다.

'TIL💡 > Algorithms' 카테고리의 다른 글

[백준] 2252: 줄 세우기 (feat.위상정렬)  (0) 2022.05.04
[백준] 5430: AC  (0) 2022.05.03
최단 경로 문제  (0) 2022.05.02
[백준] 1931: 회의실 배정  (0) 2022.05.02
[백준] 3687 성냥개비  (0) 2022.05.02