C++11中的指针空值nullptr

时间:2014.05.07

地点:基地

-----------------------------------------------------------------------------

一、为什么要有指针空值nullptr

在良好的编码习惯中,声明一个指针并对其进行初始化非常重要,未初始化的悬挂指针常导致一些难以调试的错误。往常,我们常这样初始化指针变量:

int* my_ptr1=0;
int* my_ptr2=NULL;

但我们知道,NULL其实是一个宏定义,字面常量为0,即上述两种方式本质上是一样的。于是,这样就有了一些麻烦,比如函数重载时,我们定义了如下两个版本的函数:

#include<iostream>
using namespace std;
void f(char* c)
{
	cout << "invoke f(char* c)" << endl;
}
void f(int i)
{
	cout << "invoke f(int)" << endl;
}
int main()
{
	f(0);
	f(NULL);
	f((char*)0);
	f(nullptr);
	return EXIT_SUCCESS;
}

结果如下:

可见,f(NULL)并没有调用想要的指针版本,而是调用了f(int)版本,这是因为NULL被定义为0,编译器总是优先把0视为一个整型常量造成的。0在C++98中是有二义性的,编译器首先解释它是一个整型常量,其次是一个无类型指针(void*)。

-----------------------------------------------------------------------------

二、问题的解决

C++11中,首先为了兼容性考虑并没消除0的二义性,但给出了一种新的方案,使用指针空值nullptr去初始化指针。指针空值的类型被命名为nullptr_t。它是这么来的:

typedef decltype(nullptr) nullptr_t;

充分利用了decltype 。即nullptr也是有类型的。且仅可以被隐式转化为指针类型。于是f(nullptr)会调用f(char*)版本。这样用户也就能表达自己的意图了。

-----------------------------------------------------------------------------

三、类型nullptr_t

上面我们已经知道nullptr的类型为nullptr_t,我们再看看这种类型有什么特点

1.nullptr_t是一种内置数据内型

2.nullptr_t类型 数据可以隐式转换为任意一种指针类型,但无论你想什么方式都不能转换为非指针类型。

3.nullptr_t类型数据不可用于算术运算

4.nullptr_t类型数据可以用于同类型数据之间进行关系运算。

所以诸如:

if(nullptr);
if(nullptr==0);

是不能编译通过的。

值得注意的是nullptr_t看起来像个指针类型,但其实不是的,它就是nullptr_t这样一种类型,比如在模板中就不能当做是一种指针类型传递给模板参数了,模板是推导不出它的具体类型的,必须显式转换:

template<typename T>void g(T* T){}
......
g(nullptr);   //编译错误
g((float*)nullptr);  //可推导出T为float

另外

sizeof(nullptr_t)==sizeof(void*)

即nullptr)_t所占的内存空间大小和void*相同,但他们两者的内涵是不一样的。nullptr是一个编译时期的常量,能为编译器识别。而(void*)0只是一个强制转换表达式,返回一个void* 指针类型的数据而已。而且nullptr到任何指针的转换都是隐式的。而且我们不要对nullptr进行去地址操作,因为它是一个右值常量,取nullptr的地址通常也没有意义。

C++11中的指针空值nullptr,布布扣,bubuko.com

时间: 2024-10-06 23:59:29

C++11中的指针空值nullptr的相关文章

C++11中智能指针的原理、使用、实现

目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序的效率,但是整体来说堆内存的管理是麻烦的,C++11中引入了智能指针的概念,方便管理堆内存.使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存. 理解智能指针需要从下面三个层次: 从较浅的层面看,智能指针是利用了一种叫做RAII(资

c++11之智能指针

在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存.这种内存管理的方式只需要程序员将new操作返回的指针作为auto_ptr的初始值即可,程序员不能显式的调用delete.如 auto_ptr(new int);    这在一定程度上避免了堆内存忘记释放造成的问题.不过auto_ptr也有一些缺点(拷贝是返回一个左值,不能调用delete[]等),所以在c++11中被废弃了.c++11标准照中

C++11中的智能指针

在C++11中,引入了智能指针.主要有:unique_ptr, shared_ptr, weak_ptr.这3种指针组件就是采用了boost里的智能指针方案.很多有用过boost智能指针的朋友,很容易地就能发现它们之间的关间: std boost 功能说明 unique_ptr scoped_ptr 独占指针对象,并保证指针所指对象生命周期与其一致 shared_ptr shared_ptr 可共享指针对象,可以赋值给shared_ptr或weak_ptr.指针所指对象在所有的相关联的share

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

C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 (and Why You Should Care),赖勇浩做了一个中文翻译在这里.所以,我就不翻译了,我在这里仅对文中提到的这些变化"追问为什么要引入这些变化"的一个探讨,只有知道为了什么,用在什么地方,我们才能真正学到这个知识.而以此你可以更深入地了解这些变化.所以,本文不是翻译.因为写

c++中的指针问题

c++和C语言一样,都有指针,指针通过变量的存储位置访问变量内容并进行修改,与引用不同的是,引用仅仅是给变量取一个别名,并不是一个对象,而指针则是一个对象. 1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int i=5; 6 int &temp_i=i; 7 cout<<i<<endl; 8 temp_i=6; 9 cout<<i; 10 } 上述代码为引用的例子,通过引

一起学习c++11——c++11中的新语法

c++11新语法1: auto关键字 c++11 添加的最有用的一个特性应该就是auto关键字. 不知道大家有没有写过这样的代码: std::map<std::string, std::vector<std::shared_ptr<std::list<T> > > > map; std::map<std::string, std::vector<std::shared_ptr<std::list<T> > > >

c++11 NULL、0、nullptr

C的NULL 在C语言中,我们使用NULL表示空指针,也就是我们可以写如下代码: int *i = NULL;foo_t *f = NULL; 实际上在C语言中,NULL通常被定义为如下: #define NULL ((void *)0) 也就是说NULL实际上是一个void *的指针,然后吧void *指针赋值给int *和foo_t *的指针的时候,隐式转换成相应的类型.而如果换做一个C++编译器来编译的话是要出错的,因为C++是强类型的,void *是不能隐式转换成其他指针类型的,所以通常

C++11 中值得关注的几大变化(一)

首先呢,小编觉得c++17虽然已经出来了,c++20也即将面世,但是并不代表着C++11 的没落,我们现在所学到的C++知识大多还是C++11 的,并不是书本不更新,而是其仍然起着重要的作用!接下来我们就来看看C++11中的一些值得关注的几大变化吧! Lambda 表达式 Lambda表达式来源于函数式编程,说白就了就是在使用的地方定义函数,有的语言叫"闭包",如果 lambda 函数没有传回值(例如 void ),其回返类型可被完全忽略. 定义在与 lambda 函数相同作用域的变量

C++11中多线程库

一.linux 线程同步 线程是在操作系统层面支持的,所以多线程的学习建议还是先找一本linux系统编程类的书,了解linux提供多线程的API.完全完全使用系统调用编写多线程程序是痛苦,现在也有很多封装好的多线程库,但是了解多线程系统对学习编写多线程程序非常有好处.总的来说linux提供了四类系统用于多程序程序,分别线程的创建.销毁(thread),用于线程同步的(互斥量(mutex).条件量(cond),信号量(sem)). 互斥量通过锁的机制实现线程间的同步.互斥量是一种特殊的变量,可以对