08 Dec 2022

<aside> ❓ 백준 문제를 풀 때 std::cin.tie(nullptr)를 자주 호출하곤 한다. 일단 이걸 쓰면 속도는 빨라진다고 하니 쓰긴 쓰는데, 도대체 tie는 무엇이고 왜 nullptr을 넣으면 속도가 빨라질까? 무작정 따라하지만 말고 원리는 알고 쓰자!

</aside>

std::cin.tie(nullptr). std::endl 대신 ‘\\n’. std::ios_base::sync_with_stdio(false). 이젠 하도 많이 입력해서 지겨울 정도이다. 꽤 자주 등장하는 이 세 녀석들. 일단 쓰면 문제가 빨리 풀리니까, 쓰라고 하니까 일단 쓴다. 그런데 도대체 왜 빨라지는걸까? 한번이라도 의심을 가져봤다면, 이 세 녀석에 대해 깊게, 하지만 쉽게 설명할테니, 지금 바로 출발해 보자!

Table of Contents


버퍼와 flush

속도가 빨라지는 이유에 대해 이해하려면 std::cin, std::cout과 같은 친구들이 버퍼를 사용한다는 점을 이해해야 한다. 버퍼(buffer)란 무엇인가? 버퍼는 임시 저장소라고 볼 수 있다.

예를 들어 우리가 문서 작업을 하고 있다고 생각해 보자. 문서에 쓰고싶은 내용을 쓰다가, 적당하다고 생각되는 때에 문서를 저장한다. 우리가 매일매일 해오던 일인데, 사실 문서를 열면 그 문서 원본이 아니라 문서의 복사본이 열린다. 우리는 원본이 아니라 복사본에서 작업을 하고 있던 것이다. 저장을 눌러야 비로소 작업했던 내용이 실제 파일에 적용된다. 이 복사본 문서가 바로 버퍼이다. 그 문서를 원본에 적용하는 일을 flush라고 한다.


iostream과 버퍼

iostream의 모든 stream들 (cout, cin, cerr, clog와 그 wide stream들)은 버퍼를 각각 가지고 있다. (cerr는 버퍼를 가지고는 있지만 버퍼되지 않는다.) 버퍼를 사용하면 읽고 쓰는 속도가 빨라진다. 위의 문서 예시에서 한 글자를 칠 때마다 저장을 눌러야 한다고 생각해 보자. 그것보다 충분히 몇 문장을 입력하고 나서 저장 버튼을 누르는 게 더 효율적일 것이다. 비슷한 원리 때문에 글자를 하나하나 보내지 않고(글자 하나하나마다 flush 하지 않고) 버퍼를 이용해서 한 번에 보내면(버퍼에 글자들을 모았다가 한 번에 flush하면) 속도가 빨라지는 것이다.

cout << 으로 글자들을 전달하면, 바로 콘솔에 출력되는 것이 아니다. buffer에 모은 후에, flush를 해야 비로소 콘솔에 글자들이 나타나는 것이다. 마찬가지로 cin으로 글자들을 전달받으면, 바로 c++프로그램에 전달되는게 아니라 buffer에 모았다가 flush를 해야 비로소 프로그램에 전달되는 것이다. (다만 cin의 flush는 메서드도 없을 뿐더러 보통 신경쓸 필요가 없다.)


tie! 묶음!