백준 문제를 풀다보면 평범하게 cin, cout을 사용해 코드를 작성하면 시간초과로 오답이 뜰때가 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <iostream> using namespace std; int A, B, n = 0; int main() { ios::sync_with_stdio(false); cin.tie(NULL); int a = 0; while (1) { cin >> n; if (1 <= n && n <= 1000000) break; } for (int i = 1; i < (n + 1); i++) { while (1) { cin >> A >> B; if (1 <= A && A <= 1000 && 1 <= B && B <= 1000) break; } cout << A + B << “\n”; } return 0; } | cs |
그럴땐 위의 코드처럼
1 2 | ios::sync_with_stdio(false); cin.tie(NULL); | cs |
이 부분을 추가해주면 된다.
ios_base::sync_with_stdio 구문은 C의 stdio와 C++의 iostream을 동기화 시켜주는 역할을 하는데 이걸 비활성화시켜줌으로써 C++만의 독립적인 버퍼를 생성해줘 사용하는 버퍼의 수가 줄어들게된 덕에 실행속도가 빨라지게 된다.
하지만 동기화 됬을 때의 C++ 버퍼는 thread-safe 하기 때문에 모든 입출력의 순서가 예상한 것과 정확히 일치함을 보장할 수 있는 것에 반해 동기화가 비활성화되게 되면 멀티 쓰레드 환경에서는 출력 순서를 보장할 수 없게된다.
그리고 stdio 라이브러리와 버퍼가 분리되었기 때문에 C++의 cin, cout 과 C의 scanf, gets, getchar, printf, puts, putchar 등을 함께 사용하면 안된다.
cin.tie(NULL); 코드는 cin과 cout의 묶음을 풀어주는 코드이다.
기본적으로 cin과 cout은 묶여있고 묶여있는 스트림들은 한 스트림이 다른 스트림에서 각 입출력 작업을 진행하기 전에 자동으로 버퍼를 비워줌을 보장하는데 이걸 묶음을 풀어줌으로써 버퍼를 비워주는 작업을 하지않게 되고 입출력이 그만큼 더 빨라지게 된다.
하지만 입출력의 순서를 보장받을 수 없다는 단점이 존재한다.
1 2 3 | cout << A + B << endl; cout << A + B << “\n”; | cs |
endl 대신 ‘\n’을 사용하는 것도 입출력 속도 향상에 도움이된다.
endl에도 버퍼를 비워주는 기능이 있는데 그냥 ‘\n’을 사용해서 줄바꿈을 해주면 마찬가지로 버퍼를 비워주는 작업을 하지않게되기 때문에 입출력이 더 빨라질 수 있다.