C++

std::ios_base::sync_with_stdio와 cin.tie로 입출력을 빠르게!!

LimeCoding 2022. 1. 18. 13:03

백준 문제를 풀다가 std::ios_base::sync_with_stdio과 cin.tie ,cout.tie를 같이 쓰는 코드를 보고 이게 무슨 코드일까 찾아보다가 입출력을 빠르게 하는 코드라는 것을 알아서 왜 그런지 좀 더 조사해보기로 했다.

 

 

sync_with_stdio

 

C++ 레퍼런스에서는 std::ios_base::sync_with_stdio를 다음과 같이 설명한다.

  1. C++표준 스트림들이 C 표준 스트림들과 각각의 입출력 연산 후에 동기화 할지 여부를 설정한다.
  2. 동기화가 되면 C++ 스트림들이 자신의 버퍼를 사용하지 않고 C 스트림 버퍼를 직접 사용한다.
    이는 C++입출력과 C입출력을 혼합해서 사용할 수 있게 해준다. 또한 쓰레드 안정성이 보장된다.
  3. 동기화를 하지 않을 경우 C++ 스트림들은 자신들에게 해당되는 버퍼를 사용한다.
    이 경우 입출력 연산 속도를 빠르게 해준다.

 

여기서 3번에 입출력 연산 속도를 빠르게 해주는 효과가 있는데 이는 동기화 과정을 생략하고 자신의 버퍼를 이용하여 입출력 연산을 하기 때문에 속도가 향상되는 것이다. 즉 이 코드는 입출력 속도를 빠르게 해주는 코드가 아니라 C++와 C 스트림의 동기화를 끊어주는 코드이고 동기화를 끊어준 결과로 오는 효과중에 하나가 빠른 입출력 속도인 것이다.

하지만 이 코드를 통해 속도를 올리는 것은 안정성이 매우 떨어지는 방법이다. 2번에 동기화로 인한 쓰레드 안정성 보장이 되는데 동기화를 끊어버리면 단일 쓰레드에서는 문제가 없을 수 있으나 2개 이상의 쓰레드를 사용하게 되면 입출력 순서가 엉킬 수도 있다. 그러므로 입출력 속도를 높이고 싶다면 printf나 scanf와 같은 함수를 사용하는 것이 좋다.

 

cin.tie와 cout.tie

 

std::ios_base::sync_with_stdio와 같이 쓰이는 코드로cin.tie와 cout.tie가 있다.

 

cin.tie와 cout.tie는 서로 동기화되어 있는 것을 끊어주는 역할을 한다.

std::cout << "숫자를 입력해 주세요 : ";
std::cin >> number;

 위 코드를 실행했을 때 cin과 cout이 서로 묶여있는 상태에서는 cout으로 버퍼가 채워졌을 때 cin을 불러오면 자동으로 버퍼를 flush하면서 입력받을 준비를 한다. cin.tie(NULL)로 묶여있는 상태를 풀 수 있는데 이렇게 되면 위의 문자열은 출력되지 않고 입력을 받으려는 상태가 되어 버린다. 코딩 테스트의 경우 형식이 중요하지 않기에 사용해도 큰 문제가 안될 수 있으나 예기치 못한 상황이 발생할 수 있기 때문에 사용에 주의를 기울여야한다.