NULL、0、nullptr
C的NULL
在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码:
foo_t *f = NULL;
实际上在C语言中,NULL通常被定义为如下:
也就是说NULL实际上是一个void
*的指针,然后吧void *指针赋值给int *和foo_t
*的指针的时候,隐式转换成相应的类型。而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void
*是不能隐式转换成其他指针类型的,所以通常情况下,编译器提供的头文件会这样定义NULL:
#define NULL 0
#else
#define NULL ((void *)0)
#endif
C++的0
因为C++中不能将void
*类型的指针隐式转换成其他指针类型,而又为了解决空指针的问题,所以C++中引入0来表示空指针,这样就有了类似上面的代码来定义NULL。实际上C++的书都会推荐说C++中更习惯使用0来表示空指针而不是NULL,尽管NULL在C++编译器下就是0。为什么C++的书都推荐使用0而不是NULL来表示空指针呢?我们看一个例子:
在foo.h文件中声明了一个函数:
这个函数在a.cpp、b.cpp中调用了,分别是:
a.cpp:

bar(a, b);

b.cpp:

bar(a, 0);

好的,这些代码都是正常完美的编译运行。但是突然在某个时候我们功能扩展,需要对bar函数进行扩展,我们使用了重载,现在foo.h的声明如下:
void bar(sometype1 a, int i);
这个时候危险了,a.cpp和b.cpp中的调用代码这个时候就不能按照期望的运行了。但是我们很快就会发现b.cpp中的0是整数,也就是在overload
resolution的时候,我们知道它调用的是void bar(sometype1 a, int
i)这个重载函数,于是我们可以做出如下修改让代码按照期望运行:
我知道,如果我们一开始就有bar的这两个重载函数的话,我们会在一开始就想办法避免这个问题(不使用重载)或者我们写出正确的调用代码,然而后面的这个重载函数或许是我们几个月或者很长一段时间后加上的话,那我们出错的可能性就会加大了不少。貌似我们现在说道的这些跟C++通常使用0来表示空指针没什么关系,好吧,假设我们的调用代码是这样的:
foo.h
a.cpp

bar(a, b);

b.cpp

bar(a, NULL);

当bar的重载函数在后面加上来了之后,我们会发现出错了,但是出错的时候,我们找到b.cpp中的调用代码也很快可能忽略过去了,因为我们用的是NULL空指针啊,应该是调用的void
bar(sometype1 a, sometype2
*b)这个重载函数啊。实际上NULL在C++中就是0,写NULL这个反而会让你没那么警觉,因为NULL不够“明显”,而这里如果是使用0来表示空指针,那就会够“明显”,因为0是空指针,它更是一个整形常量。
在C++中,使用0来做为空指针会比使用NULL来做空指针会让你更加警觉。
C++ 11的nullptr
虽然上面我们说明了0比NULL可以让我们更加警觉,但是我们并没有避免这个问题。这个时候C++ 11的nullptr就很好的解决了这个问题,我们在C++ 11中使用nullptr来表示空指针,这样最早的代码是这样的,
foo.h
a.cpp

bar(a, b);

b.cpp

bar(a, nullptr);

在我们后来把bar的重载加上了之后,代码是这样:
foo.h
void bar(sometype1 a, int i);
a.cpp

bar(a, b);

b.cpp

bar(a, nullptr);

这时候,我们的代码还是能够如预期的一样正确运行。
在没有C++ 11的nullptr的时候,我们怎么解决避免这个问题呢?我们可以自己实现一个(《Imperfect C++》上面有一个实现):
{
public:
template<class T>
inline operator T*() const
{ return 0; }
template<class C, class T>
inline operator T C::*() const
{ return 0; }
private:
void operator&() const;
} nullptr = {};
虽然这个东西被大家讨论过很多次了,但是我觉得还是有必要再讨论一下,毕竟在C++ 11还没有普及之前,我们还是应该知道怎么去避免问题,怎么很快的找到问题。
from:http://www.cppblog.com/airtrack/archive/2012/09/16/190828.aspx
NULL、0、nullptr的更多相关文章
- Javascript 中的false、0、null、undefined和空字符串对象
在Javascript中,我们经常会接触到题目中提到的这5个比较特别的对象——false.0.空字符串.null和undefined.这几个对象很容易用错,因此在使用时必须得小心. 类型检测 我们下来 ...
- php中NULL、false、0、" "有何区别?
php中很多还不懂php中0,"",null和false之间的区别,这些区别有时会影响到数据判断的正确性和安全性,给程序的测试运行造成很多麻烦.先看一个例子: <? $str ...
- empty和is_null以及isset函数在0、”0”、‘空串’、NULL、false、array()的计算值
1empty:只要是非空或者非零的值都返回false,换句话说‘’.‘0’.0.null.false都返回true: 2is_null: 当参数满足下面三种情况时,is_null()将返回TRUE,其 ...
- c++11 NULL、0、nullptr
C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #de ...
- 史上最明白的 NULL、0、nullptr 区别分析(老师讲N篇都没讲明白的东东),今天终于明白了,如果和我一样以前不明白的可以好好的看看...
C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL; foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #def ...
- Javascript中那些你不知道的事之-- false、0、null、undefined和空字符串
话不多说直接进入主题:(如果有写的不对的地方欢迎指正) 我们先来看看他们的类型分别是什么: typeof类型检测结果 结论:false是布尔类型对象,0是数字类型对象,null是object对象,un ...
- oracle基础:怎样把查询的null转换为0、打印、定义变量
https://blog.csdn.net/xuxile/article/details/49943665 oracle怎样把查询的null转换为0 1.查询的null转换为0 NVL(Expr1,E ...
- NULL、0、nullptr的区别
某些时候,我们需要将指针赋值为空指针,以防止野指针. 有人喜欢使用NULL作为空指针常量使用,例如:int* p = NULL;. 也有人直接使用0值作为空指针常量,例如:int* p = 0;. ...
- NULL、NUL、‘\0’、0以及EOF
0 is an integer constant, '\0' is a character constant, nul is the name of the character constant. N ...
随机推荐
- C#中的线程(三)多线程
C#中的线程(三)多线程 Keywords:C# 线程Source:http://www.albahari.com/threading/Author: Joe AlbahariTranslator ...
- 如何将Emmet安装到到 Sublime text 3?第二部分该插件还能让我们自定义快捷键呼出某个浏览器以预览页面
看清楚哦~~这是Sublime text 3不是2的版本,两者的安装还是有区别的,下面的方法是我感觉比较简单的,其他的要命令什么的感觉太复杂了,经测试是OK的. 先关闭Sublime text 3: ...
- SQL使用指南(1)—— 数据定义语言(DDL)
1.使用create 语句创建表 CREATE TABLE table_name (column_name datatype[null|not null], column_name datatype[ ...
- UVA - 11014 Make a Crystal (莫比乌斯反演)
给定一个n*n*n的立方体(中心点为原点O),选择尽量多的点,使得对于任意两点A,B,B不在线段OA上. 可以发现,原问题可转化为三维坐标下的点(x,y,z)中有多少个点的gcd(x,y,z)=1. ...
- New Year and Buggy Bot
Bob programmed a robot to navigate through a 2d maze. The maze has some obstacles. Empty cells are d ...
- C#异步编程(二)用户模式线程同步
基元线程同步构造 多个线程同时访问共享数据时,线程同步能防止数据损坏.不需要线程同步是最理想的情况,因为线程同步存在许多问题. 第一个问题就是它比较繁琐,而且很容易写错. 第二个问题是,他们会损害性能 ...
- C#面向对象(三):多态
前文链接: C#面向对象(一):明确几个简单的概念作为开胃菜 C#面向对象(二):封装和继承 今天来聊聊面向对象的多态,这部分算是比较重要和核心的,很多工作2年多的程序员其实对于面向对象和多态的理解也 ...
- HIVE-执行distribute by时报错的解决过程---之如何分析hive执行的错误并解决
在执行一条HIVE语句的时候报了以下错误,重新检查了所有步骤,重启所有服务,发现没有问题. 但发现一个有趣的事情 1,select sno,sname,sex,sage,sdept from stud ...
- poj 2154 Color——带优化的置换
题目:http://poj.org/problem?id=2154 置换的第二道题! 需要优化!式子是ans=∑n^gcd(i,n)/n (i∈1~n),可以枚举gcd=g,则有phi( n/g )个 ...
- Linux基础命令-系统时间
Linux启动时从硬件读取日期和时间信息,读取完成以后,就不再与硬件相关联 Linux的两种时钟 系统时钟:由Linux内核通过CPU的工作频率进行的: date:显示系统时间 +%D +%F dat ...