카테고리 없음

C++11 nullptr

차차냥 2023. 2. 18. 14:49

C++ 에서 쓰이는 NULL 은 0과 동일하다.

가리키는 포인터가 없으면 그 주소는 0이기 때문이다.

stdio.h 에서 NULL을 정의하는 부분을 살피면 한 번에 알 수 있다.

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

 

NULL 과 0, 동일한 int 타입이다.

 

nullptr 을 쓰는이유

(1) 오동작 방지

void Test(int a)
{
	cout<< "Test(int)" <<endl;
}

void Test(void* ptr)
{
	cout<< "Test(*)" <<endl;
}

// 본문
int main()
{
    Test(0);		// Test(int a) 함수 호출
    Test(NULL); 	// Test(int a) 함수 호출
    
    Test(nullptr); 	// Test(void* ptr) 함수 호출
}

두 Test 함수 중에서 아래의 함수인 포인터를 활용하고 싶음에도 불구하고, NULL == 0 이므로 자동으로 Test(int a) 함수를 호출하는 상황이 생긴다. 그러나 nullptr 를 인자로 넣었을 때는 Test(void* ptr) 함수를 호출 할 수 있다.

이처럼 nullptr는 사용하는 함수가 overloading 되어 있을 때, 0이나 NULL을 썼을 경우에 제대로 호출되지 않는 문제를 해결 할 수 있다.

이런 오동작을 방지하기 위해서라도 nullptr 를 쓴다.

 

(2) 가독성이 높아진다

// 클래스 만들어주기
class Object
{
	// empty
};

Object* findObject()
{
    return nullptr;
};

int main()
{
    auto object = findObject();
    if(object == nullptr)
    {
    	return 0;
    }
    return 0;
}

 

auto를 사용하게 될 경우, 코드를 그냥 쭉 읽었을 때 이 object 의 자료형을 쉽게 추론하기 어렵다. findObject라는 함수의 반환값을 찾아보면 알 수는 있겠지만,  F12를 눌러 또 타고 들어가야 하는 귀찮음이 동반되니까.. (사실 뭐.. F12하나 누르는게 뭐가 귀찮냐고 할 수도 있지만..)

이 때 nullptr 를 보고, "아~ 포인터를 저장하는 변수구나" 하고 쉽게 알게 된다.

이러한 가독성을 높이는데 도움을 준다.

 


Nullptr를 구현해보기

class NULLptr
{
public:
    // 그 어떤 타입의 포인터와도 치환 가능
    template<typename T>
    operator T* () const
    {
    	return 0;
    }

    // 그 어떤 타입의 멤버 포인터와도 치환 가능
    template<typename C, typenameT>
    operator T C::* () const
    {
    	return 0;
    }

    // 주소값 유출을 막는다
    void operator&() const = delete;
};

// nullptr 과 동일한 역할을 할 수 있게 된다.
const NULLptr _NULLptr;

 

참고로 nullptr의 타입은 std::nullptr_t 로,

기존에 사용하던 NULL이나 0을 static_cast를 사용해서 nullptr 로 캐스팅이 가능하다.

int* ptr1 = static_cast<std::nullptr_t>(NULL);
int* ptr2 = static_cast<std::nullptr_t>(0);

 

참고 : [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강좌 - Rookiss