空指针:从 0 到 NULL,再到 nullptr
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相关推荐
- 《Effective Morden C++》Item 8: Prefer nullptr to 0 and NULL.
引子 这一条目就比较简单了,就是宣传用nullptr来指代空指针,而不是之前的0或者NULL. 正文 在老式C++中,显然0是int类型,而NULL也是一个整数类型(int或者long).总的来说,这 ...
- Effective Modern C++[实践]->优先使用nullptr,而非0或NULL
优先使用nullptr 回看旧识 空指针 `void*` 在`c++`中必须显式地将`malloc`的返回值类型转换为`(int *)`. 不知`void *`所指,如何强转 `void*` 不能直接 ...
- [EMC++] Item 8. Prefer nullptr to 0 and NULL
条款八 倾向使用nullptr而非0和NULL 简介 在C++中的字面量0是一个int,当C++在一个只可以使用指针的情景中找到0,它勉强地把其解释为null指针. 对于NULL也有类似的问题,具体实 ...
- C++11中0与 NULL与nullptr之间的关系
1.从本质上1) 0是int型的字面值常量2) NULL 是预处理变量,定义在 cstdlib 中,其值是03) nullptr 是 nullptr_t 类型的字面值. 2.cstdlib 中 NUL ...
- php中0与NULL,False,“0”,\0的区别
先说明一下结论:0与NULL,False,"0","\0"的值相同,都以0存储,但是类型不同, 再看一段实验代码: <?php $test=0; if($ ...
- 64位环境0和NULL的区别
0 & NULL 在C语言中将值为0的指针作为NULL,NULL通常被定义为0或((void *)0); 有很多应该使用NULL的地方写0代替的程序,通常这样的写法也不会发生问题,如: cha ...
- 关于Error in render: TypeError: Cannot read property '0' of null问题的解决方法
关于Error in render: "TypeError: Cannot read property '0' of null"问题的解决方法 //这里是原生代码块,也就是运行该块 ...
- 没有core文件时定位segfault at 0 ip (null) 的问题(三):艰难定位,多种原因
可以先阅读前面两篇文章: https://blog.csdn.net/lianshaohua/article/details/107642136 https://blog.csdn.net/lians ...
- Javascript中的0,false,null,undefined,空字符串对比
先看一段代码: <script type="text/javascript">alert(typeof (false) === "boolean") ...
最新文章
- python简单爬虫入门一_Python简单爬虫入门二
- html中dom和bom,区分BOM和DOM,区分window、document、html、body
- 配置ssh 无需密码即可登录远程服务器
- 【Python】list tuple
- ValueStack中的context与ActionContext的区别
- 多个项目共用同一个redis_浅谈Redis分布式锁(上)
- 关于React Hooks使用
- robocopy 中的/MIR参数
- 第一章---近红外光谱概述2(近红外光谱分析难点及解决思路)
- DirectX 11
- IP、 TCP、 UDP协议
- 苹果ajax请求,请求苹果系统请求ajax提示没找到配置文件
- FTP服务器的两种工作模式
- OPPO A59s刷机包_OPPOA59s线刷包刷机教程
- SSM+人才交流平台 毕业设计-附源码221022
- 500G 史上最全的JAVA全套教学视频网盘
- 吃鸡ios和android灵敏度,和平精英灵敏度怎么调最稳2020二指攻略:安卓苹果灵敏度调节方法大全[多图]...
- flutter 运行失败 The SDK directory 'xxxxx' does not exist.
- 教你如何自己写一个微信小游戏「跳一跳」外挂
- AR+教育:ALVA SYSTEMS把图书馆做成了4D百科全书
热门文章
- iOS-NSThread编程详解
- 基于粒子滤波的物体跟踪
- [Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
- 【数据结构与算法】之深入解析“交错字符串”的求解思路与算法示例
- SwiftUI之从前端视角看SwiftUI语言
- 使用python判断流媒体mp3格式
- 深度学习——02、深度学习入门——经典卷积神经网络架构实例——RNN
- 【Tiny4412】Tiny4412烧写uboot脚本分析
- 【计算机类】大学生计算机专业常用工具汇总
- swing打地鼠游戏_【亲子早教】9月早教亲子游戏