본인은 C++을 이용해서 백준 문제를 풀고있다. 그런데 풀다가 이상한 광경을 목격했다. 다른 사람의 코드를 봤는데, 분명 코드 구조는 같은데 실행 시간이 훨씬 빨랐다. 뭐가 다른걸까 비교해보니 내 코드에는 두 줄이 없었다.
ios::sync_with_stdio(false);
cin.tie(NULL);
C++로 알고리즘을 풀 때 cin, cout은 속도가 느리다.
C++의 cin, cout는 scanf, printf에 비해 속도가 현저히 느리다.
cin, cout을 printf, scanf만큼 빠르게 쓸 수 있는 방법이 있다.
ios::sync_with_stdio(false);
cin.tie(NULL);
이 두 줄이 무슨 뜻일까
stdio.h는 C에서 printf, scanf를 사용할 수 있는 헤더이다.
iostream은 C++에서 cout, cin을 사용할 수 있는 헤더이다.
cin, cout은 기본적으로 C의 stdio.h와 동기화되어있다.
stdio.h의 버퍼와 iostream의 버퍼를 같이 쓴다는 말이다. 동기화를 유지하는 작업이 추가되다 보니 상대적으로 속도가 느리다.
버퍼(buffer) : 데이터가 전송될 때 일시적으로 그 데이터를 보관하는 메모리 영역
여기서 stdio.h와 동기화를 안해주면 어떻게 될까?
iostream 버퍼만 쓰게되어 버퍼가 줄어든다. 그럼 속도가 빨라지는 것이다.
ios::sync_with_stdio의 기본 디폴트 값은 true이다. stdio.h와 동기화해서 쓰겠다는 것이다. ios::sync_with_stdio()에 false 값을 넣어주면 동기화가 해제된다.
stdio.h와 동기화해서 쓰는 이유는 입력 버퍼링을 방지하기 위함이라고 한다. 알고리즘에서는 입력 형식이 제한되어있어 입력 버퍼링 방지를 할 필요가 없다.
근데 유의할 점이 있다.
C의 입출력 방식과 동시 사용 불가 (printf, scanf, getchar, puts, gets)
-> 동기화를 해제했기 때문에 C의 버퍼와 C++의 버퍼가 독립적이다. 따라서 출력되는 순서를 보장할 수 없다.
멀티쓰레드 불가 - 싱글쓰레드 환경에서만 사용(실무에서 사용 불가)
입출력 속도를 빠르게 하기 위한 일종의 편법이다.
cin과 cout은 하나로 묶여있어서 서로 연결되어있다.(커플링)
cin을 통해 입력이 발생하면 cout 출력 버퍼(buffer)를 플러시(flush)시켜 출력이된 후 입력을 받는다.
버퍼(buffer)는 꽉 차면 출력이 되는 방식이다. 플러시(flush)는 버퍼가 꽉 차지 않아도 즉시 출력해서 버퍼를 비워주는 것이다.
이게 무슨말이냐
cin과 cout은 서로 연결되어있어서 cin을 쓰면 출력 버퍼를 비우고 입력이 발생한다.
이러한 플러시 과정(버퍼를 비우는 작업)도 시간이 든다.
그래서 cin, cout의 상호 연결을 끊어주기 위해 cin.tie(NULL);를 사용한다.
endl보다 "\n"이 더 빠르다. endl도 불러오는 것이기 때문이다.