최근 포토로그


[C++11] nullptr에 대해서 복잡한컴퓨터이야기

시간이 되면 C++에 대해서 틈틈이 글을 써보려도 합니다.

오늘은 무지하게 간단한 nullptr의 이야기를 해볼까 합니다.

nullptr은 C++11에 추가된 새로운 keyword 이며, null pointer를 의미합니다. 이것이 중요한 이유는 기존에 써오시던 NULL이라는 것의 정의가 0L 이기 때문에 태생적으로 혼돈스러울 수 밖에 없었던 몇가지 issue를 해결할 수 있기 때문입니다.
사용 법이야 간단합니다.

const char *p = nullptr; // p 는 null pointer가 되는 것이지요.
if (p) ...     // expression 평가는 fail 이겠지요
int i = nullptr;   // 이 구문은 이제 안됩니다. nullptr은 더 이상 int로 변환되지 않습니다

기존에 0과 NULL에 대해서는 정상적으로 동작합니다.

int *p1 = nullptr;
int *p2 = 0;
int *p3 = NULL;

if (p1 == p2 && p1 == p3) {...}

NULL은 실제로 어떻게 정의되어 있을지 조금 궁금하시죠? stdio.h 에는 NULL을 아래와 같이 정의하고 있습니다.(VS2012에서 살펴보았습니다.)

/- Define NULL pointer value *-
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

즉 C++에서 NULL은 정확히 0과 동일합니다.
여기서 한가지 말씀드리자면 nullptr은 std::nullptr_t 타입입니다. 다른 널 포인터 타입 들은 static_cast를 사용하면 casting이 가능합니다.

int *p4 = static_cast<std::nullptr_t>(NULL);    // 기존에 사용하던 널 포인터 타입인 NULL은 이렇게 casting하실 수 있습니다.
int *p5 = static_cast<std::nullptr_t>(0);    // 기존에 사용하던 0 는 이렇게 casting 하실 수 있습니다.

0 이나 NULL이나 모두 int type 이니까 아래와 같이 하면 어떨까 궁금하실 수도 있을 것 같습니다.

int *p6 = static_cast<std::nullptr_t>(1);    // 하지만 이렇게는 안됩니다.

std::nulptr_t는 nullptr을 위해서만 존재하는 type이라고 볼 수 있겠지요.

약간 더 실질적인 예제를 한번 살펴보겠습니다.

void f(int *ptr);
void f(int val);

f(nullptr);    // f(int *ptr)이 호출됩니다.
f(0);    // f(int val)이 호출됩니다.
f(NULL);    // f(int val)이 호출됩니다.

f() 함수가 위의 예와 같이 overloading 되어 있을때, 0이나 NULL을 썼을 경우 포인터로 평가되지 못하는 문제를 해결하였지요.

아래와 같은 template 작성에도 좋은 예가 있을 수 있습니다.

template<typename F, typename P>
void logAndCall(F func, P param)
{
    func(param);
}

void f(int *p);

f(0);        // 괜찮아 보입니다. void f(int p)가 정의되어 있지 않으므로 f(int *p)가 정상 호출 되지요
f(nullptr); // 당연히 됩니다.

logAndCall(f, 0); // 이것도 에러가 됩니다. P의 type이 int로 평가되기 때문에 func(int)를 찾게되겠지요
logAndCall(f, NULL); // 이것도 에러입니다. 위와 같은 이유입니다.
logAndCall(f, nullptr); // 오호라~ 이건 정상적으로 P가 std::nullptr_t로 추론됩니다. f(std::nullptr_t)를 찾지요. 이건 기존 포인터와 호환되므로 정상적으로 func(int *p)를 호출합니다.

nullptr과 nullptr_t 을 추가함으로서 제대로 널 포인터의 의미를 부여할 수 있게 된것 같아요.
이제는 NULL이나 0 보다는 nullptr을 꼭! 쓰시는 것이 좋을 것 같습니다.


덧글

  • 상훈이 2012/10/24 02:11 # 삭제 답글

    형 좋은글 잘 봤습니다.. 감사합니다~~
  • arubirate 2015/11/15 17:26 # 삭제 답글

    감사합니다. 잘봤습니다:D

    퍼가도 될까요?
댓글 입력 영역


facebook 프로필 위젯

트위터 위젯