이번엔 지금까지 써왔던 입출력에 대해서 알아보자.
C++은 입력과 출력을 바이트들의 흐름(스트림)이라 간주한다. 입력 시 프로그램은 입력 스트림으로부터 바이트들을 추출하고, 출력 시에는 출력 스트림에 바이트를 삽입한다. 이 바이트들은 수치 데이터나 문자의 2진 표현을 나타낼 수 있다. 스트림은 수도꼭지의 출구와 쏠 곳을 이어주는 파이프와 비슷하다. 여기서는 물이 바이트 역할을 한다.
일반적으로 버퍼를 활용하면 입출력을 좀 더 효율적으로 처리할 수 있다. 버퍼는 정보를 전송할 때 임시 저장 장치로 이용되는 메모리 블록이다. 이게 왜 효율적인가? 예를 들어 프로그램이 하드디스크에 있는 어떤 정보를 읽으려면 한 문자를 읽어서 처리하고, 또 한 문자를 읽어서 처리하고...를 반복한다. 만약 버퍼를 사용한다면? 처음부터 버퍼에 많은 양을 가져온다. 그리고는 버퍼에서 한 문자씩 읽어들인다. 그러다가 다 읽으면 또 한 뭉큼을 버퍼로 가져온다. 하드 디스크로부터 직접 읽는 것보다 이렇게 버퍼에서 읽는 게 훨씬 빠르다. 이것은 마치 산에서 물 떠올 때, 한 번에 많은 물을 떠오는 것이랑 비슷하다.
마찬가지로 출력을 할 때 프로그램은 버퍼를 일단 채운 뒤, 데이터를 하드 디스크로 전송하고, 다음 번 출력을 위해 깨끗히 비운다. 이걸 '버퍼 비우기'라고 부른다. 대개의 C++ 프로그램은 Enter을 누를 때 입력 버퍼를 비운다. 그래서 cin >> 같은 거 할 때 Enter을 눌러야지 내용 처리가 되는 것이다.
이런 버퍼와 스트림을 우리는 어떻게 쓸 수 있었나? <iostream>을 통해 쓸 수 있었다. <iostream>은 출력 메서드를 제공하는 <ostream> 클래스, 입력 메서드 제공하는 <istream> 클래스 둘 다한테 상속을 받는다. 기능을 사용하려면, 객체를 사용해야 한다. 출력을 처리하려면 ostream의 객체인 cout을 사용한다. 이 객체를 생성하면 하나의 스트림이 열리고, 자동으로 버퍼가 생성되고, 그 버퍼가 스트림에 연결된다. 그리고 나서 그 클래스의 멤버 함수를 쓸 수 있는 것이다. cin도 입력이라는 점만 빼면 똑같다.