C++0x(차기 C++ 표준) 미리보기 1, 널 포인터의 이름은 nullptr

류광, 2007/11/11 19:17
C++0x 미리보기 첫 회. 0 또는 매크로 NULL로 표현했던 널 포인터에 nullptr이라는 이름이 붙게 되었습니다.

C++0x라고 부르는 차기 C++ 표준을 간단하게 소개하는 글들을 연재하고자 합니다. C++ 표준 위원회에서 차기 C++ 표준 명세서에 포함시키기로 결정한 제안들을 하나씩 해설하는 것이 목표입니다.

차기 C++ 표준 개정 작업은 크게 두 부분, 즉 언어 자체의 확장과 표준 라이브러리의 확장으로 나뉘는데요(그 외에 기존 표준의 구멍이나 애매함을 고치는 작업도 있습니다만 대부분 아주 기술적인 부분입니다). 이 연재에서는 언어 자체에 대한 제안들을 이야기하겠습니다. 표준 라이브러리의 확장은 얼마 전 나온 번역서 C++ 표준라이브러리 확장 : 튜토리얼 및 레퍼런스로 충분히 커버가 될 것입니다.

C++ 표준 위원회는 여러 언어 확장 제안들의 표준 포함 여부를 "State of C++ Evolution"이라는 제목의 문서로 공개합니다. 이 문서는 계속해서 갱신되는데, 현재 최신의 "State of C++ Evolution" 문서는 N2432 입니다. 이 연재는 최근 "State of C++ Evolution" 문서에서 "Integrated into working paper(명세서 초안에 포함되었음)"에 나열된 제안들을 대상으로 합니다.


첫 회는 0 또는 매크로 NULL로 표현했던 널 포인터에 번듯한 이름을 붙이자는 제안입니다.

  • 제안의 명칭: A name for the null pointer: nullptr
  • 제안자: H. Sutter, B. Stroustrup
  • 관련 문서: N1488, N1601, N2214, N2431

(이하에서 예제 코드들은 N2431에서 가져온 것입니다.)

C++에서 널 포인터를 0으로 표기할 수 있습니다. 그런데 0은 다른 의미로도 쓰이는 값입니다. 우선 0은 정수 0을 의미하기도 하고 부동소수점 수 0.0을 의미하기도 합니다. 또한 부울의 false를 의미하기도 합니다. 이 때문에 함수 중복적재에서 의도하지 않은 문제들이 발생합니다. 예를 들어

void f(int);  // (1)
void f(char*); // (2)

이 있을 때 f(0)은 항상 (1)로 해소됩니다. 만일 널 포인터를 인수로 해서 (2)를 호출하고 싶다면 번거롭게 명시적인 강제 형변환을 사용해서 f((char*)0);이라고 표기해야 합니다. 한편 다음과 같은 일관되지 못한 현상도 발생합니다.

std::string s1( false ); // (3) 컴파일 됨
std::string s2( true ); // (4) 그러나 이것은 컴파일 오류

(3)의 경우 false는 0으로 간주되고, 0은 다시 (char*)0으로 간주되어서 char*를 받는 string 생성자가 호출됩니다. 반면 (4)의 경우 컴파일러는 string에 bool을 받는 생성자가 없다고 간주하고 오류를 냅니다.

이런 일들을 방지하기 위해서는 널 포인터를 0과는 다른 무엇인가로 지칭할 수 있어야 합니다. 결론적으로 제안자들은 nullptr이라는 새로운 예약어의 도입을 제안했고, 표준 위원회는 그 제안을 받아들였습니다. 이후 C++0x이 공표되고 그것을 지원하는 컴파일러가 나오면 0이나 (T*)0 대신 nullptr을 사용할 수 있습니다.

"해야 한다"가 아니라 "할 수 있다"라고 표현한 것은, 예전처럼 0을 널 포인터를 의미하는 용도로 사용하는 것도 여전히 허용되기 때문입니다(하위 호환성을 위해). 예를 들어 char* ch = nullptr;과 char* ch = 0;은 같은 의미입니다.

지금까지 제안의 이유와 결론만 간단하게 요약한 셈인데요. 2007년 11월 현재 이 제안의 최신 문서인 N2431에는 새 예약어 도입이 아닌 다른 대안들(nullptr이라는 새 클래스를 표준 라이브러리에 추가하는 것과 (void*)0이라는 표기를 사용하는 것등)이나 nullptr 외의 다른 이름들(0P, 0p 등)에 대해서도 논의합니다. 호환성이나 컴파일러 제작 측면에서 부담스러운 새 예약어의 도입을 피하기 위해 최대한 고민한 흔적이 보입니다. 문서 후반부는 표준 명세서 문구의 추가, 수정안인데 이 부분은 보통의 프로그래머가 반드시 읽을 필요는 없겠고요.

top
트랙백 2 : 의견 # + 5

Trackback Address :: http://occamsrazr.net/tt/trackback/170

  1. Tracked from Yagur의 Juggling 2008/03/18 19:27 DELETE

    Subject: C++0x 미리보기

    저와 지인들 사이에서 번역 공장으로 알려진 류광님의 C++Ox 미리보기입니다. 차기 표준에 관심이 있으신분들이 보시면 흥미로운것들이 많습니다. 류광님의 C++Ox 미리보기 2007/11/11 C++0x(차기 C++..
  2. Tracked from 김윤수의 이상계를 꿈꾸며 2008/08/20 01:19 DELETE

    Subject: C++ 이야기 스물두번째: 0이 널포인터일까 ?

    "0이 널포인터일까요 ?" 다음 코드를 한 번 보시겠어요 ? 컴파일이 잘 될까요 ? #include <boost/shared_ptr.hpp> class Nil { }; int main() { Nil* np = 0; boost::shared_ptr<Nil> p1(np); boost::shared_ptr<Nil> p2(0); } 0이 널포인..
comments powered by Disqus

(2013년 11월 10일자로 블로그에도 DISQUS 시스템을 도입했습니다. 기존 의견의 수정, 삭제, 댓글 추가는 여전히 가능합니다.)

  1. object 2007/11/11 20:17 PERMALINKMODIFY/DELETE REPLY

    유익한 글 잘 봤습니다. 언어의 설계와 구현에 있어서 얼마나 많은 미묘하고 골치아픈 점이 많은지를 잘 알 수 있는 단적인 예이네요. 참고하신 곳으로 가보니 많은 제안들이 있고 흥미로운 주제가 참 많네요. 특히 C/C++에서 enum이 가지는 제약에 대해 항상 불만이었는데 enum class라는 것이 제안이 되어 반갑군요.

    그런데 "해야 한다"는 shall, must, should 중에 어떤 것인가요? "할 수 있다"는 may인 것 같습니다만.

  2. 류광 2007/11/12 00:42 PERMALINKMODIFY/DELETE REPLY

    다음 회도 기대해 주세요 :) enum class에 대해서도 언젠가는 소개하겠습니다.

    "해야 한다"는 영어를 염두에 두고 쓴 것은 아니었지만 must에 해당한다고 봐야겠네요. RFC 2119( http://www.ietf.org/rfc/rfc2119.txt )에 따르면 must와 shall은 동일합니다.

  3. 고어핀드 2007/11/14 20:52 PERMALINKMODIFY/DELETE REPLY

    아하, 저런 허점이 있었군요. 지금까지도 c++을 썼으면서도 저런 허점이 있었다는 걸 모르고 있었다는 게 부끄럽습니다 ^_^;

  4. 류광 2007/11/15 18:59 PERMALINKMODIFY/DELETE REPLY

    저런 허점을 몰랐다는 것은 오히려 좋은 프로그래밍 습관을 가지고 계시다는 증거가 아닐까요^^

    자주는 힘들겠지만 꾸준히 연재하겠습니다~

  5. 김윤수 2008/08/20 01:21 PERMALINKMODIFY/DELETE REPLY

    shared_ptr 을 쓰다가 비슷한 문제를 경험해서 트랙백 남깁니다.