KoreanFoodie's Study

Effective Modern C++ | 항목 8 : 0 과 NULL 보다 nullptr 를 선호하라 본문

Tutorials/C++ : Advanced

Effective Modern C++ | 항목 8 : 0 과 NULL 보다 nullptr 를 선호하라

GoldGiver 2022. 10. 26. 09:51

C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!

항목 8 : 0 과 NULL 보다 nullptr 를 선호하라

핵심 :

1. 0 과 NULL 보다 nullptr 를 선호하라.
2. 정수 형식과 포인터 형식에 대한 오버로딩을 피하라.

 

리터럴 0은 int 이지 포인터가 아니다. 포인터만 사용할 수 있는 위치에 0 이 있으면 C++ 은 마지못해 이를 null 포인터로 해석하지만, 이는 최후의 수단일 뿐이다.

// f 의 세 가지 오버로딩
void f(int);
void f(bool);
void f(void*);

...

// f(void*) 가 아닌 f(int) 호출
f(0);

// 컴파일 되지 않거나, f(int) 호출
f(NULL);

// f(void*) 호출
f(nullptr);

nullptr 의 장점은 이것이 정수 형식이 아니라는 점이다. 사실 포인터 형식도 아니다. nullptr 는 모든 형식의 포인터라고 생각하면 된다. nullptr 의 실제 형식은 std::nullptr_t 인데, std::nullptr_t 자체는 다시 "nullptr 의 형식" 으로 정의된다. std::nullptr_t 는 모든 raw pointer 형식으로 암묵적으로 변환된다!

 

nullptr 는 템플릿을 사용할 때 특히 중요하다. 다음과 같은 코드가 있다고 해 보자.

template<
	typename FuncType,
	typename MuxType,
	typename PtrType>
auto lockAndCall(
	FuncType func,
	MuxType& mutex,
	PtrType ptr) -> decltype(func(ptr))
{
	using MuxGuard = std::lock_guard<MuxType>;

	MuxGuard g(mutex);
	return func(ptr);
}

...

int f1(std::shared_ptr<Widget> spw);
double f2(std::unique_ptr<Widget> upw);
bool f3(Widget* pw);

std::mutex f1m, f2m, f3m;

...

// 오류! 0 은 int 여서 ptr 가 int 로 연역됨
auto result1 = lockAndCall(f1, f1m, 0);

// 오류! NULL 은 정수 형식으로 연역되어 ptr 가 int 로 연역됨
// 필자의 컴퓨터에서 NULL 은 'long long int' 로 취급되고 있었다
auto result2 = lockAndCall(f2, f2m, NULL);

// 정상!
auto result3 = lockAndCall(f3, f3m, nullptr);

 

Comments