C++11 中,nullptr 是空指针,可用来给 (指向任意对象类型的) 指针赋值

广义整型 (integral types) = char, short, int, long, long long and their unsigned counterparts, and bool, wchar_t, char16_t, and char32_

1  调用重载函数

C++ 中,0 首先被视为 int 型,而 NULL 首先被视为广义整型 (integral types),至于具体是 int,long 或是其它,要视相应的情况而定

下面三个函数,因为形参类型的不同,构成重载函数。如果各传递三个不同的实参,来选择调用哪个函数,则会出现如下问题:

// three overloads of f
void f(int);
void f(bool);
void f(void*); f(); // calls f(int), not f(void*)
f(NULL); // might not compile, but typically calls f(int). Never calls f(void*)
f(nullptr); // calls f(void*) overload

1) C++ 视 0 首先为 int 型,因此,调用 f(0) 即调用 f(int)

2) NULL 的情况复杂些,C++ 首先视其为广义整型。假如 NULL 被定义为普通的 0,则调用 f(int);

如果 NULL 被定义成 0L,则 long -> int, long -> bool, 0L -> void*, 这三种情况都是合法的,此时,编译器会报错

3) 使用 nullptr,则不会有重载函数调用模糊的问题

- nullptr 不属于广义整型,也不是普通意义上的指针。

- nullptr 的实际类型是 std::nullptr_t,它能够隐式的转换成所有的原始指针类型,故可将其视为一个可指向所有类型的指针。

2  代码清晰

使用 nullptr 代替 0 或 NULL,能显著提高代码的清晰度,尤其是和  auto 连用时,如下:

auto result = findRecord( /* arguments */ );
if (result == ) {
...
} auto result = findRecord( /* arguments */ );
if (result == nullptr) {
...
}

使用 0 与 result 作比较,则一时不能确定 findRecord 的返回值类型 (可能是广义整型,也可能是指针类型); 使用 nullptr,可以清楚地知道 findRecord 的返回值,必定是一个指针类型

3  模板函数

当程序中有模板 (template) 时, nullptr 的好处更加明显:

// 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); // calling code that wants to pass null pointers
std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
using MuxGuard = std::lock_guard<std::mutex>; ...
{
MuxGuard g(f1m); // lock mutex for f1
auto result = f1(); // pass 0 as null ptr to f1
} // 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

lock mutex -> call function -> unlock mutex,这个模式在程序中重复了三次,要想避免这种重复,可用一个模板函数代替

template<typename FuncType, typename MuxType, typename PtrType>
auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr)) // C++11
{
MuxGuard g(mutex);
return func(ptr);
}

最后,调用该模板函数

auto result1 = lockAndCall(f1, f1m, );          // error!
...
auto result2 = lockAndCall(f2, f2m, NULL); // error!
...
auto result3 = lockAndCall(f3, f3m, nullptr); // fine

当 0 作为实参传递给 lockAndCall 函数时,其被 C++ 推断为 int 型,这与 f1 所期望的 std::shared_ptr<Widget> 型参数明显不符,因此出现报错。

同理,NULL 与 f2 期望的 std::unique_ptr<Widget> 型参数也不符合。

nullptr,作为 ptr 传给 f1 或 f2 时,被推断为 std::nullptr_t ; 作为 ptr 传给 f3 时,std::nullptr_t 会隐式的转换成 Widget*,确保了参数类型的一致

小结:

1)  prefer nullptr to 0 and NULL

2)  avoid overloading on integral and pointer types

参考资料

<Effective Modern C++> item 8

<C++ Programming Language>  "integral types"

C++11 之 nullptr的更多相关文章

  1. C++11之nullptr

    [C++11空指针] 1.NULL的问题 class Test { public: void TestWork(int index) { std::cout << "TestWo ...

  2. C++11空指针: nullptr

    参考[C++11]新特性--引入nullptr NULL 在C++中, 经常会用到空指针, 一般用NULL表示空指针, 但是NULL却是这样定义的 #ifndef NULL #ifdef __cplu ...

  3. c++11 NULL、0、nullptr

      C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #de ...

  4. c++11新特性(了解)

    从C++出来到现在已经13年了. Bjarne Stroustrup(C++的创造者)最近评价C++:”感觉像个新的语言“. 事实上,C++11核心已经发生了很重大的变化: . 支持Lambda表达式 ...

  5. C++ 11 之学习总结

    感慨时间过的好快,C++ 11出来都5年了,现在才开始学习,但为时也不晚: 主要是网上及身边的朋友大肆宣扬C++ 11的某些优化,弄得别人心里痒痒的,所以就花了3天学习了点基本知识,相对于整个C++ ...

  6. C++11 能好怎?

    0. 摘要 近期读了一些关于C++11标准的材料. 本篇博客将从新标准的优点.与旧版本的区别和使用方法三个角度,大致介绍我对C++11的认识. C++11标准,原名C++0x, 是03版旧标准的更新. ...

  7. 聊一聊c++中指针为空的三种写法 ----->NULL, 0, nullptr

    看到同事用了一下nullptr.不是很了解这方面东东,找个帖子学习学习 http://www.cppblog.com/airtrack/archive/2012/09/16/190828.aspx N ...

  8. C++11 中值得关注的几大变化(网摘)

    C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 ...

  9. C++11 带来的新特性 (1)

    1 语法改进 1.1 模板表达式中的空格 在c++03 及以前 vector<list<int>>; //Error vector<list<int> > ...

随机推荐

  1. salesforce 零基础学习(二十七)VF页面等待(loading)效果制作

    进行查询的情况下,显示友好的等待效果可以让用户更好的了解目前的状态以及减少用户消极的等待,例如下图所示. VF提供了<apex:actionStatus>标签,,此标签用于显示一个AJAX ...

  2. IDE:Eclipse查看Servlet源码

    一.源码下载 1.打开tomcat官网:http://tomcat.apache.org/    , 点击右侧下载菜单(以tomcat-7为例)进入下载页面:http://tomcat.apache. ...

  3. Mongodb安装与配置详解

    简介: mongodb作为一款通用型数据库,除了能够创建,读取,更新和删除数据外,还提供一系列不断扩展的独特功能. a.索引: mongodb支持二级索引,允许多种快速查询,且提供和唯一索引,复合索引 ...

  4. Xdebug 配置

    到官网 http://www.xdebug.com/download.php 下载 找到对应PHP版本的 Xdebug ,后面带 TS 的为线程安全,本机环境为 win7 64 + php-5.5.1 ...

  5. Struts2第一个例子Hello World!

    1.首先用eclipse新建一个动态web项目Struts2Demo1: (把Default output floder由build\classes改成WebContent\WEB-INF\class ...

  6. 【Discuz】云平台服务:出了点小错,由于站点ID/通信KEY等关键信息丢失导致Discuz!云平台服务出现异常

    提示信息 出了点小错,由于站点ID/通信KEY等关键信息丢失导致Discuz!云平台服务出现异常 版本X3.2.20160601 解决方案 Step1.修改云平台开通状态为未开通状态 Step2.访问 ...

  7. 深入理解CSS变形transform(3d)

    × 目录 [1]坐标轴 [2]透视 [3]变形函数 [4]透视函数 [5]变形原点 [6]背景可见 [7]变形风格 前面的话 本文将详细介绍关于transform变形3D的内容,但需以了解transf ...

  8. hdu4292Food(最大流Dinic算法)

    /* 题意:每一个人都有喜欢的吃的和喝的,每一个人只选择一个数量的吃的和一个数量的喝的,问能满足最多的人数!? 思路:建图很是重要!f-food, p-people, d-drink 建图: 0(源点 ...

  9. Cocos2d-x 3.2 学习笔记(十三)CocoStudio UI编辑器 by 保卫萝卜

    关于编辑器部分研究的不多,但基本能使用.最近时间不是很多,因此写blog的次数越来越少了.自从玩了<保卫萝卜>时候一直想要写一下,同时练下手感.基本的结构已经写的差不多了,主要完善写UI和 ...

  10. 云计算之路-阿里云上:消灭“黑色n秒”第三招——禁用网卡的TCP/IP Offload

    程咬金有三板斧,我们有三招.在这篇博文中我们要出第三招,同时也意味着昨天在“希望的田野”上的第二招失败了. 前两招打头(CPU)不凑效,这一招要换一个部位,但依然要坚持攻击敌人最弱(最忙最累)部位的原 ...