본문 바로가기

[C++] 왜 0이나 NULL이 아닌 nullptr을 사용해야 할까?

Kwonriver 2022. 1. 22.
728x90

0이나 NULL의 경우 형식이 포인터의 형식이 아니다.

0의 경우 포인터의 위치에 있으면 단순히 널포인터로 인식만 할 뿐이다.

0은 단순히 int일 뿐이다.

NULL 또한 마찬가지이다.

 

그렇다면 0과 NULL을 쓰는 것이 왜 문제일까?

오버로딩된 다양한 함수

위와 같이 오버로딩된 함수들이 있다고 하자.

이 때 사용자가 func(0)을 사용했다.

그렇다면 위 세가지 함수 중 어떤 함수가 실행될 것인가?

 

당연히 func(int n) 함수를 호출할 것이다.

그렇다면 void func(void* vp)를 호출하고 싶은데 인자로 null을 넣고 싶으면 어떻게 해야하는가

0 과 NULL 둘 다 func(void* vp)를 호출 할 수 없다.

결국 답은 nullptr 뿐이다.

 

nullptr은 정수의 형식이 아니다.

모든 형식의 포인터인데 nullptr의 실제 형식은 std::nullptr_t이다.

std::nullptr_t는 다시 nullptr의 형식으로 정의된다.

따라서 std;:nullptr_t는 모든 포인터 형식으로 암묵적 변환이 일어나며 이 때문에 nullptr은 모든 형식의 포인터처럼 사용이 가능하다.

 

또 다른 장점은 nullptr을 사용함으로써 코드의 명확성을 높일 수 있다는 것이다.

특히나 auto가 사용된 코드에서 더욱 빛을 발한다.

 

위와 같은 코드가 있을 때 result의 자료형은 무엇일까?

int 형이라고 100% 확신할 수 있는가??

나의 경우 다음처럼 많이 사용한다.

 

result가 포인터의 형식일 때 위와 같이 많이 사용한다.

그럼 위의 result가 포인터 형식이라고 확신할 수 있을까?!

 

답은 없다이다.

0은 그저 int형 상수일 뿐이다.

NULL 또한 사실상 포인터의 형식이 아니다.

따라서 다음과 같이 사용하면 result가 포인터라고 명확히 명시할 수 있다.

 

이렇게 하면 result는 100% 확실하게 포인터의 형식이다.

int형이 될 수 없다.

 

따라서 nullptr은 코드를 명확하게 할 수 있는 요인이 될 수 있다.

 

nullptr은 템플릿이 관여할 때에도 빛을 발한다.

뮤텍스(임계영역을 만드는 클래스)를 잠근 상태에서만 호출해야하는 함수가 있다고 가정하고, 그 함수들이 각자 다른 종류의 포인터를 받는다고 하자.

그 함수들은 다음과 같다.

 

shared_ptr과 unique_ptr은 <memory>에 있다.

 

다음은 널 포인터로 이들을 호출하는 예시이다.

 

 

우리는 널 포인터로서의 사용을 보고 있다.

매개변수에 0과 NULL을 사용한 첫번째와 두번째 모두 코드는 작동한다.

그런데 이 위에 3가지 방법이 다 똑같아 보이지 않는가?
이를 템플릿 함수화 하자.

 

함수명이 이해가 안된다면 다음 포스팅을 보자.

http://blog.naver.com/ram1029123/220581956140

 

개인 저장용 : 네이버 블로그

개인 저장용

blog.naver.com

위 함수를 사용하여 다시 만든다면 다음과 같다.
 
보이는가?!
저 위와 달리 0과 NULL을 사용한 경우 에러가 발생한다!
에러를 읽어보자.
 
이유를 찾아보자
우리의 3번째 인수는 PtrName으로 되어있다.
템플릿 형식이기 때문에 사실상 어떤 변수가 넘어와도 상관없다.
그래서 int형 변수가 들어가도 상관이 없는게 정상이다.
그런데 에러가 발생한다
이는 Func가 매개변수로 int를 받지 않기 때문이다.
첫번째 매개변수로 들어간 함수의 매개변수는 포인터형식이다.
그런데 int는 포인터 형식이 아니다.
따라서 함수의 마지막부분인 funcName(ptr)을 수행할 수가 없게된다.( 포인터형식에 int를 넣은 꼴 )
따라서 에러가 발생하지만 nullptr은 그 자체로 포인터이기 때문에 수행에 문제가 없다.
 
위 예시처럼 템플릿 자료형 추론이 0과 NULL을 포인터가 아닌 실제 형식으로 사용된다는 사실은
널포인터를 사용할 때 0 또는 NULL이 아닌 nullptr을 사용함을 명확시해주는 요인이다.
그러니 널포인터를 사용할 때 0 또는 NULL이 아닌 nullptr을 사용하자.
728x90