nullptr

空指针:从 0 到 NULL,再到 nullptr

NULL 是一个宏定义:

#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
int *my_ptr = 0;
int *my_ptr = NULL;
// NULL 的问题
#include <stdio.h>void f(char *c) {printf("invoke f(char *)\n);
}
void f(int i) {printf("invoke f(int)\n");
}
int main() {f(0);f(NULL);     // 注意:如果gcc编译,NULL会转换为内部标识符 __null,该语句会编译失败f((char*)0);
}
/** 使用 XLC 编译器会得到如下结果:* invoke f(int)* invoke f(int)* invoke f(char*)* XLC 将 NULL 定义为了 0
*/

引起该问题的原因是 0 的二义性。0 既可以表示整型,也可以表示一个 空指针(void *)。存在二义性时,需要使用强制类型转换:((void *)0).

虽然 g++ 编译器将 NULL 转换为编译器内部标识符(__null),并在编译时期进行了分析,在一定程度上可以缓解问题,但是会带来代码移植的限制。

nullptr

// 头文件: cstddef
typedef decltype(nullptr) nullptr_t;
/*使用 nullptr_t 必须包含头文件: cstddef。使用 nullptr 则不需要
*/

nullptr 最大的优势是 有类型,且可以被隐式转换为指针类型。

#include <stdio.h>void f(char *c) {printf("invoke f(char *)\n);
}
void f(int i) {printf("invoke f(int)\n");
}
int main() {f(nullptr); // invoke f(char *)f(0);       // invoke f(int)
}

nullptr 和 nullptr_t

C++11 不仅定义了空指针常量 nullptr,也定义了 空指针类型 nullptr_t。那么也就是说 nullptr_t 可以用来定义变量。通常,可以使用 nullptr_t 声明一个 空指针变量。

  • C++11规定:

    • 所有定义为 nullptr_t 类型的数据都是等价的,行为也是完全一致。
    • nullptr_t 类型数据可以隐式转换为任意一个指针类型。
    • nullptr_t 类型数据不能转化为 非指针类型,即使使用 reinterpret_cast<nullptr_t>()。
    • nullptr_t 类型数据不适用于算术运算表达式。
    • nullptr_t 类型数据可以用于关系运算表达式,但仅能与 nullptr_t 类型数据或指针类型数据做比较,当且仅当关系运算符为 ==, <=, >=时返回 true.
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{// nullptr 可以隐式转换为 char*char *cp = nullptr;// 不可转换为整型,而其他类型也不能转换为 nullptr_t// int n1 = nullptr;// int n2 = reinterpret_cast<int>(nullptr);// nullptr 与 nullptr_t 类型变量可以比较// 当使用 ==, <=, >= 符号比较时返回 true。nullptr_t nptr;if (nptr == nullptr) {cout << "nullptr_t nptr == nullptr" << endl;} else {cout << "nullptr_t nptr != nullptr" << endl;}if (nptr < nullptr) {cout << "nullptr nptr < nullptr" << endl;} else {cout << "nullptr_t nptr !< nullptr" << endl; }// 不能转换为整型或 bool 类型// if (0 == nullptr);// if (nullptr);// 不可以进行算术运算// nullptr += 1;// nullptr * 5;// 以下操作均可以正常运行sizeof(nullptr);typeid(nullptr);throw(nullptr);return 0;
}

虽然 nullptr_t 看起来像是一个 指针类型,但是在把 nullptr_t 应用于模板时,我们发现模板却只能把他作为一个普通的类型来推导。(并不会将其视为 T* 指针)

using namespace std;
template<typename T> void g(T* t) {}
template<typename T> void h(T t) {}int main()
{g(nullptr);          // error,nullptr 时 nullptr_t 类型,而不是指针g((float*)nullptr);  // T = floath(0);                // T = inth(nullptr);          // T = nullptr_th((float*)nullptr);  // T = float *}

一些关于 nullptr 规则的讨论

  • sizeof(nullptr_t) == sizeof(void *)

  • nullptr 是一个编译时期的常量,它的名字是一个编译时期的关键字,能够为编译器识别。

  • (void *)0 只是一个强制转换表达式,其返回的也是一个 void * 指针类型

  • nullptr 到任何指针的转换都是隐式的。

  • nullptr 对象的地址可以被用户使用

#include <cstdio>
#include <cstddef>
using namespace std;
int main()
{nullptr_t my_null;printf("%x\n", &my_null);// printf("%x", &nullptr);  // 根据 C++11 的规定,nullptr 是右值常量,无法取地址printf("%d\n", my_null == nullptr);const nullptr_t && default_nullptr = nullptr;// default_nullptr 是 nullptr 的一个右值引用printf("%x\n", &default_nullptr);
}

空指针:从 0 到 NULL,再到 nullptr相关推荐

  1. 《Effective Morden C++》Item 8: Prefer nullptr to 0 and NULL.

    引子 这一条目就比较简单了,就是宣传用nullptr来指代空指针,而不是之前的0或者NULL. 正文 在老式C++中,显然0是int类型,而NULL也是一个整数类型(int或者long).总的来说,这 ...

  2. Effective Modern C++[实践]->优先使用nullptr,而非0或NULL

    优先使用nullptr 回看旧识 空指针 `void*` 在`c++`中必须显式地将`malloc`的返回值类型转换为`(int *)`. 不知`void *`所指,如何强转 `void*` 不能直接 ...

  3. [EMC++] Item 8. Prefer nullptr to 0 and NULL

    条款八 倾向使用nullptr而非0和NULL 简介 在C++中的字面量0是一个int,当C++在一个只可以使用指针的情景中找到0,它勉强地把其解释为null指针. 对于NULL也有类似的问题,具体实 ...

  4. C++11中0与 NULL与nullptr之间的关系

    1.从本质上1) 0是int型的字面值常量2) NULL 是预处理变量,定义在 cstdlib 中,其值是03) nullptr 是 nullptr_t 类型的字面值. 2.cstdlib 中 NUL ...

  5. php中0与NULL,False,“0”,\0的区别

    先说明一下结论:0与NULL,False,"0","\0"的值相同,都以0存储,但是类型不同, 再看一段实验代码: <?php $test=0; if($ ...

  6. 64位环境0和NULL的区别

    0 & NULL 在C语言中将值为0的指针作为NULL,NULL通常被定义为0或((void *)0); 有很多应该使用NULL的地方写0代替的程序,通常这样的写法也不会发生问题,如: cha ...

  7. 关于Error in render: TypeError: Cannot read property '0' of null问题的解决方法

    关于Error in render: "TypeError: Cannot read property '0' of null"问题的解决方法 //这里是原生代码块,也就是运行该块 ...

  8. 没有core文件时定位segfault at 0 ip (null) 的问题(三):艰难定位,多种原因

    可以先阅读前面两篇文章: https://blog.csdn.net/lianshaohua/article/details/107642136 https://blog.csdn.net/lians ...

  9. Javascript中的0,false,null,undefined,空字符串对比

    先看一段代码: <script type="text/javascript">alert(typeof (false) === "boolean") ...

最新文章

  1. python简单爬虫入门一_Python简单爬虫入门二
  2. html中dom和bom,区分BOM和DOM,区分window、document、html、body
  3. 配置ssh 无需密码即可登录远程服务器
  4. 【Python】list tuple
  5. ValueStack中的context与ActionContext的区别
  6. 多个项目共用同一个redis_浅谈Redis分布式锁(上)
  7. 关于React Hooks使用
  8. robocopy 中的/MIR参数
  9. 第一章---近红外光谱概述2(近红外光谱分析难点及解决思路)
  10. DirectX 11
  11. IP、 TCP、 UDP协议
  12. 苹果ajax请求,请求苹果系统请求ajax提示没找到配置文件
  13. FTP服务器的两种工作模式
  14. OPPO A59s刷机包_OPPOA59s线刷包刷机教程
  15. SSM+人才交流平台 毕业设计-附源码221022
  16. 500G 史上最全的JAVA全套教学视频网盘
  17. 吃鸡ios和android灵敏度,和平精英灵敏度怎么调最稳2020二指攻略:安卓苹果灵敏度调节方法大全[多图]...
  18. flutter 运行失败 The SDK directory 'xxxxx' does not exist.
  19. 教你如何自己写一个微信小游戏「跳一跳」外挂
  20. AR+教育:ALVA SYSTEMS把图书馆做成了4D百科全书

热门文章

  1. iOS-NSThread编程详解
  2. 基于粒子滤波的物体跟踪
  3. [Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
  4. 【数据结构与算法】之深入解析“交错字符串”的求解思路与算法示例
  5. SwiftUI之从前端视角看SwiftUI语言
  6. 使用python判断流媒体mp3格式
  7. 深度学习——02、深度学习入门——经典卷积神经网络架构实例——RNN
  8. 【Tiny4412】Tiny4412烧写uboot脚本分析
  9. 【计算机类】大学生计算机专业常用工具汇总
  10. swing打地鼠游戏_【亲子早教】9月早教亲子游戏