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

NULL:

NULL是c语言的东西,定义处: #define NULL ((void *)0)

我们可以写  int* i = NULL, foo_t* pObj = NULL.

NULL实际上是一个void *的指针,然后吧void *指针赋值给int *和foo_t *的时候,会隐式转换成相应的类型。而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void *是不能隐式转换成其他指针类型的,所以通常情况下,编译器提供的头文件会这样定义NULL:

#ifdef __cplusplus
#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
void bar(type1 a, type2* b); //foo.h中的bar函数在a.cpp和b.cpp中都被调用了. //a.cpp
.....
bar(a,b);
..... //b.cpp
.....
bar(a, );
..... //现在,上面的代码都能编译运行.但是突然某天我们要功能扩展,需要对bar函数扩展,我们使用了重载 foo.h变成如下:
void bar(sometype1 a, sometype2 *b);
void bar(sometype1 a, int i); //这个时候就危险了.因为a.cpp和b.cpp中的调用代码这个时候就不能按照期望的运行了。但是我们很快就会发现b.cpp中的0是整数,也就是在overload resolution的时候,我们知道它调用的是void bar(sometype1 a, int i)这个重载函数,于是我们可以做出如下修改让代码按照期望运行: bar(a, static_cast<type2 *>()); //我知道,如果我们一开始就有bar的这两个重载函数的话,我们会在一开始就想办法避免这个问题(不使用重载)或者我们写出正确的调用代码,然而后面的这个重载函数或许是我们几个月或者很长一段时间后加上的话,那我们出错的可能性就会加大了不少。貌似我们现在说道的这些跟C++通常使用0来表示空指针没什么关系,好吧,假设我们的调用代码是这样的:
//foo.h
void bar(type1 a, type2 *b); //a.cpp
......
bar(a, b);
......
//b.cpp
.....
bar(a,NULL);
..... //当bar的重载函数在后面加上来了之后,我们会发现出错了,但是出错的时候,我们找到b.cpp中的调用代码也很快可能忽略过去了,因为我们用的是NULL空指针啊,应该是调用的void bar(type1 a, type2 *b)这个重载函数啊。实际上NULL在C++中就是0,写NULL这个反而会让你没那么警觉,因为NULL不够“明显”,而这里如果是使用0来表示空指针,那就会够“明显”,因为0是空指针,它更是一个整形常量。 在C++中,使用0来做为空指针会比使用NULL来做空指针会让你更加警觉。

C++ 11的nullptr

 //虽然上面我们说明了0比NULL可以让我们更加警觉,但是我们并没有避免这个问题。这个时候C++ 11的nullptr就很好的解决了这个问题,我们在C++ 11中使用nullptr来表示空指针,这样最早的代码是这样的

 //foo.h

 void bar(type1 a, type2* b);
-------------------------------------------
7 | //a.cpp | //b.cpp |
| .... | ....... |
| bar(a,b); | bar(a, nullptr);|
| ....... | ........ |
---------------------------------------------
在我们后来把bar的重载加上了之后,代码是这样: //foo.h
void bar(type1 a, type2 *b);
void bar(type1 a, int i); //a.cpp //b.cpp
.... .....
bar(a,b); bar(a,nullptr);
.... ...... //这时候,我们的代码还是能够如期的正确运行. //在没有C++11的nullptr的时候,我们应该怎么解决避免这个问题呢?我们可以自己实现一个nullptr const
class nullptr_t
{
public:
template<class T>
inline operator T*() const
{ return ; } template<class C, class T>
inline operator T C::*() const
{ return ; } private:
void operator&() const;
} nullptr = {};


和小伙伴都惊了个呆了啊...上面自己实现的nullptr_t类完全看不懂的样子,得一句一句的分析分析啊...

 const                       //参见下文解释1
class nullptr_t
{
public:
template<class T>
inline operator T* () const //参见下文解释2
{
return ;
} template<class C, class T>
inline operator T C::*() const //参见下文解释3
{
return ;
} private:
void operator& () const; //参见下文解释4 }nullptr = {}; //参见下文解释5

解释1 : 在类前面的const是什么!!

 //类前面的const 是修饰 类后面定义的对象的.

 const
class A
{
public:
int i;
}a,b; //等价于
class A
{
public:
int i;
}; const A a;
const A b;

解释2 : 这个模板函数是什么?

 template <class T>
inline operator T* () const
{
return ;
} //上面的模板函数是在重载 类型转换运算符 (跟 重载 operator = 一样都是在重载运算符).
//我们知道重载运算符是要带返回值的,例如下面的类重载等号 是要返回A&的
class A
{
public:
A& operater = (const A& Obj)
{
i = Obj.i;
j = Obj.j;
}
private:
int i;
int j;
};
//但是呢.重载 类型转换运算符比较特殊. (c++ primer,可以查“用户自定义类型转换符”找到讲解) 规定为:转换函数不能写返回类型(规定的),返回的类型就是 operator 后面跟的类型
所以:
inline operator T* () const
---------------------------------------------
这是一个类型转换函数,把A类型(这里是return 0 的 0的类型)转换成 T*的类型
inline 表示内联函数,写不写无所谓。
operator 代表重载某种操作 operator T* () 就是重载类型转换
const 表示 成员变量是只读,不能改。 return _data; // 有返回值,返回值类型是operator后面的T*类型。

解释3 : 这个模板函数又是什么???

解释4:  只写函数声明,不写函数实现真的可以么??

事实证明是可以的,只有没人调用这个函数是可以编译运行成功的..但是如果有人调用的话编译就会报错了.

解释5: 类对象 = {} 中的 ={}是什么??

= {} 是c++11的语法,代表给这个变量初始化

聊一聊c++中指针为空的三种写法 ----->NULL, 0, nullptr的更多相关文章

  1. Android平台中实现对XML的三种解析方式

    本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...

  2. Java中获取键盘输入值的三种方法

    Java中获取键盘输入值的三种方法     Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值 ...

  3. MVC3中,在control里面三种Html代码输出形式

    MVC3中,在control里面三种Html代码输出形式:ViewData["msg"] = "<br /> Title <br />" ...

  4. jquery 在页面中三种写法

    jQuery 分 2 个系列版本 1.x 与 2.x,主要的区别在于 2.x 不再兼容 IE6.7.8浏览器,这样做的目的是为了兼容移动端开发.由于减少了一些代码,使得该版本比 jQuery 1.x ...

  5. Shell脚本中字符串判空:使用-z 字符串长度为0时,为真,-n字符串长度不为0,为真。这两个都不靠谱【转】

    最近发现使用  -z   和  -n  来判断字符串判空,或不空时,很不靠谱. 使用下面的方法最可靠: if [ "x${value}" == "x" ]    ...

  6. 在Tomcat中部署web项目的三种方式

    搬瓦工搭建SS教程 SSR免费节点:http://www.xiaokeli.me 在这里介绍在Tomcat中部署web项目的三种方式: 1.部署解包的webapp目录 2.打包的war文件 3.Man ...

  7. 【转载】取得系统中网卡MAC地址的三种方法

    From:http://blog.csdn.net/zhangting1987/article/details/2732135 网卡地址这个概念有点混淆不清.因为实际上有两个地址,mac地址和物理地址 ...

  8. Tomcat中部署web应用的三种方式

    Tomcat中部署web应用的三种方式(静态部署)       第一种,针对war或解压后的war,最为常用的是直接操作webapp目录,将完整的war包或者web应用直接放到webapp目录下.使用 ...

  9. spring中创建bean对象的三种方式以及作用范围

    时间:2020/02/02 一.在spring的xml配置文件中创建bean对象的三种方式: 1.使用默认构造函数创建.在spring的配置文件中使用bean标签,配以id和class属性之后,且没有 ...

随机推荐

  1. Android开发之50个常见实用技巧——活用布局

    第一章.活用布局 Hack1. 使用weight属性实现视图的居中显示  ①合用weightSum属性和layout-weight属性 解决问题,如:居中显示按钮,并占据父视图的50%: 代码如: & ...

  2. PHP开发Apache服务器配置

    照此配置流程,绝对一路畅通,可保无虞. 昨天弄了个PHP小程序,想在本地跑一下测试,可是工作电脑没有安装环境,于是下载了一个wamp,一路畅通,Apache.Mysql.PHP就 全有了.启动wamp ...

  3. IIS- ASP站点布署时查看ASP错误信息

    ASP使用的脚本是VBSCRIPT,布置的时候想显示他的错误信息,可以在INTERNET选项里把显示友好http错误信息的勾去掉 就能查看ASP布署时查看错误信息的勾去掉.

  4. 什么是jetty

    转自:http://www.cnblogs.com/eafy/archive/2007/10/24/906792.html 1. 简介 Jetty 是一个开源的servlet容器,它为基于Java的w ...

  5. JSP http头消息

    头 描述 Accept 指定MIME类型 Accept-Charset 编码,例如utf-8 Accept-Encoding 编码方式,例如使用gzip压缩 Accept-Language 语言,例如 ...

  6. EasyUI-增删改操作

    最近公司要用easyui,这里自己看了官网几篇文章,遇到些问题,大多数的问题都是敲代码的时候笔误,其他有些地方确实需要注意一下,这里做些笔记. 1.在mysql中建好表之后修改id字段为递增字段,发现 ...

  7. [Javascript] IIFE

    Javascript modules are a design pattern that allow you to encapsulate your code into smaller self ma ...

  8. careercup-栈与队列 3.1

    3.1 描述如何只用一个数组来实现三个栈. 解答 我们可以很容易地用一个数组来实现一个栈,压栈就往数组里插入值,栈顶指针加1: 出栈就直接将栈顶指针减1:取栈顶值就把栈顶指针指向的单元的值返回: 判断 ...

  9. 基于HTML5的SLG游戏开发( 三):认识PureMVC

    在游戏开发中,对于一般网络游戏,由于需要多人协同开发,每个人负责不同的模块开发,为了减少耦合,需要用来一些MVC框架,减少模块之间的耦合.我们现在使用的mvc框架是pureMVC.pureMVC的官网 ...

  10. VC++ 响应回车键的2种方法

    众所周知,VC++响应回车键经常用的方法是利用 BOOL PreTranslateMessage(MSG* pMsg) 截取回车键消息,如: if (pMsg->message == WM_KE ...