1. Introduction
c++ 강의를 마친 후, 파릇파릇한 신입생이 메일로 질문을 했다. 내용은 trivial한 내용이었는데, 다음과 같았다.
- c와 c++ 둘다 printf를 쓸 수 있더라, printf와 std::cout의 차이점이 무엇이냐.
- std::endl과 \n의 차이점이 무엇이냐.
- using namespace std를 쓰면 바로 cout, cin 이렇게 쓸 수 있는데, 책에서는 이렇게 쓰면 굉장히 위험하다고 한다. 왜 그런 것인가?
2. Answer
첫번째 질문은 어렵지 않게 답할 수 있다. 다음은 내가 학생에게 한 답변이다.
정확하게는 iostream에 printf와 std::cout이 모두 정의되어 있음.
printf는 원칙적으로는 문자열 밖에 출력할 수 없음. 정수, 실수를 표현하려면 형식에 맞춰 캐스팅을 해줘야함.
ex) printf("%d", n); --> n이 %d(decimal) 타입임을 명시.
반면 std::cout은 자동적으로 캐스팅을 해주기 때문에 표현이 자유로움.
ex) std::cout << n; --> n이 어떤타입인지 명시할 필요없음.
이러면 std::cout이 훨씬 좋은 듯 하지만 printf는 그 자체로 한번에 출력하고 끝이지만, std::cout은 << 를 기준으로 여러절차가 혼합되어 속도가 느림.
이런 특징은 백준같은 제한된 시간에서 알고리즘을 해결할 때 불리하게 작용될 수 있음.
두번째 질문은 둘이 서로 같은 줄만 알았는데, 새롭게 알게된 점도 있어서 작성한다.
std::endl은 개행 기능임. 즉 printf의 \n과 같은 역할임.
단, 완벽하게 같지는 않음. endl은 \n을 출력하고 출력버퍼를 지우는 기능도 같이하게 되는데, 너무 자주쓰면 역시 속도가 느려질 수 있음. 이 경우 \n을 추천.
세번째 질문은 예시를 들어서 설명한다.
굉장히까지는 아니고, namespace의 중복문제가 발생할 수 있음.
ex) 만약 나중에 std말고 다른 namespace를 임포트 한다고 생각해보자.
...
using namespace std;
using namespace myNamespace; // cin이라는 함수를 포함하고 있는 namespace. -> 우리는 myNamespace의 cin을 호출하기를 원함.
...
이때 메인 함수에서 cin을 호출하면 컴퓨터는 std의 cin을 호출할지 myNamespace에서 cin을 호출할지 모호해지는거지.
책에서 굉장히 위험하다고 하는 말은 아마 이런 모호한 경우에 툴이 보내는 오류 메세지 때문일 것임.
저런 경우에서 툴이 "namespace가 같은 함수를 import해서 모호합니다" -> 이런식으로 오류 메세지를 보내주면 "내가 namespace 선언을 잘못 했구나" 하겠지만,
실제로는 컴퓨터가
1) std의 cin함수를 강제로 실행하고
2) 사용자가 myNamespace에 cin이 실행되겠지하고 넣은 인자를 std의 cin에 넣어주고
3) 이때 생기는 오류를 내보냄.
이 경우에 오류가 무슨소리를 하는건지 몰라서 해매는 경우가 있다는 거지.