《Modern Effective C++》读书笔记之条款八:优先选用nullptr而不是0或NULL

优先选用nullptr, 而不是NULL或0

直接开门见山摆事实, 字面常量0的类型是int,而非指针,C++在只能使用指针的语境发现一个0会把它解释为空指针,而NULL也无非是0的一个宏罢了,它们本身都不具备指针类型,所以当作为形参传递的时候会与int混淆
在C++11以前,NULL的定义无非以下几种

#define NULL 0
#define NULL 0LL
#define NULL (void *)0

所以在调用时会出现很多问题

void f(int);
void f(bool);
void f(void *);

f(0); // 调用f(int)
f(NULL); // 会出现编译错误

在C++11中引入的nullptr并非一个整数,你可以把它理解为任意一种类型的指针, 它可以隐式转换到所有的裸指针类型。对于上述的例子

void f(int);
void f(bool);
void f(void *);

f(0); // 调用f(int)
f(nullptr); // 调用f(void *)

除了这个优点以外,它还可以提升代码的清晰性,尤其是涉及auto变量的时候,比如

auto result = findRecord();
if (result == 0) {
	// do something
}

这样对阅读会有歧义,你不知道这个0是一个指针还是一个整数,但是如果是nulllptr就十分清晰,而不会有多义性

auto result = findRecord();
if (result == nullptr) {
	// do something
}

在涉及到模板的时候,nullptr的优点就更加明显了,比如

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

//假设调用代码是这样的
std::mutex f1m, f2m, f3m;
using MuxGuard = std::lock_guard<std::mutex>;

{
	MuxGuard g(f1m);
	auto res = f1(0);
}

{
	MuxGuard g(f2m);
	auto res = f2(NULL);
}

{
	MuxGuard g(f3m);
	auto res = f3(nullptr);
}

代码过于冗余, 我们使用模板来优化

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

using MuxGuard = std::lock_guard<std::mutex>;

template<typename FuncType, typename MuxType, typename PtrType>
decltype(auto) lockAndCall(FuncType func, MuxType &mux, PtrType ptr) {
	MuxGuard g(mux);
	return func(ptr);
}

// 调用
auto res1 = lockAndCall(f1, f1m, 0);	// 出错
auto res2 = lockAndCall(f2, f2m, NULL);	// 出错
auto res3 = lockAndCall(f3, f3m, nullptr);	// 正确

此时传入0或NULL,模板就不能正常运行,因为模板在进行推导的过程中,PtrType接受的参数是0或NULL时会被解释为int或long long,而不是指针,所以会出现编译错误,而传入nullptr就不会出现这个问题,因为nullptr是一个指针,所以模板可以正常推导

总结:

  1. nullptr是一个指针,可以隐式转换到所有的裸指针类型
  2. 相对于0或NULL,优先选用nullptr
  3. 避免在整数和指针类别的重载

参考: 《Modern Effective C++》第五版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值