Software Engineering/Programming
[Item 8] Prefer nullptr to 0 and NULL
HelloJaewon
2014. 12. 7. 22:05
The literal 0 is an int, not a pointer.
// three overloads of f void f (int); void f (bool); void f (void *); f(0); // call f(int), not f(void *) f(NULL); // might not compile, but typically calls f(int). Never calls f(void*)
This counterintuitive is what led to the guideline for C++98 programmers to avoid overloading on pointer and integral types.
That guideline remains valid in C++11, because, the advice of this item notwithstanding, it's likely that some developers will continue to use 0 and NULL, even though nullptr is a better choice.
Advantages of nullptr
- It doesn't have an integral type.
f(nullptr); // calls f(void*) overload
- It can also improve code clarity.
auto result = findRecord( /* arguments */ ); if (result == 0) { .... }
auto result = findRecord( /* arguments */ ); if (result == nullptr) { .... }
- nullptr shines especially brightly when templates enter the picture.
// call these only when the appropriate mutex is locked int f1 (std::shared_ptr<WIdget> spw); double f2 (std::unique_ptr<Widget> upw); bool f3 (Widget * pw); std::mutex f1m, f2m, f3m; // mutexes for f1, f2 and f3 using MuxGuard = std::lock_guard<std::mutex>; // C++ typedef; see Item 9 ... { MuxGuard g(f1m); // lock mutex for f1 auto result = f1(0); // pass 0 as null ptr to f } // unlock mutex ... { MuxGuard g(f2m); // lock mutex for f2 auto result = f2(NULL); // pass NULL as null ptr to f2 } // unlock mutex ... { MuxGuard g(f3m); // lock mutex for f3 auto result = f3(nullptr); // pass nullptr as null ptr to f3 } // unlock mutex
template<typename FuncType, typename MuxType, typename PtrType> auto lockAndCall (FuncType func, MuxType & mutex, PtrType ptr) -> decltype(func(ptr)) { MuxGuard g(mutex); return func(ptr); } auto result1 = lockAndCall(f1, f1m, 0); // error! ... auto result2 = lockAndCall(f2, f2m, NULL); // error! ... auto result3 = lockAndCall(f3, f3m, nullptr); // fine
template<typename FuncType, typename MuxType, typename PtrType> decltype(auto) lockAndCall (FuncType func, // C++14 MuxType & mutex, PtrType ptr) { MuxGuard g(mutex); return func(ptr); }
Things to Remember
- Prefer nullptr to 0 and NULL.
- Avoid overloading on integral and pointer types.