内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
这段代码概念上对三个指针(安全指针初始化)执行相同的操作:
int* p1 = nullptr; int* p2 = NULL; int* p3 = 0;
那么,赋值指针有什么好处呢?nullptr
将值分配给他们NULL
或0
?
在这段代码中,似乎没有优势。但请考虑以下重载函数:
void f(char const *ptr); void f(int v); f(NULL); //which function will be called?
哪个函数会被调用?当然,这里的意图是f(char const *)
,但在现实中f(int)
会被召唤!这是个大问题,不是吗?
因此,解决这些问题的方法是使用nullptr
:
f(nullptr); //first function is called
当然,这并不是唯一的优势nullptr
...。以下是另一个:
template<typename T, T *ptr> struct something{}; //primary template template<> struct something<nullptr_t, nullptr>{}; //partial specialization for nullptr
因为在模板中,nullptr
被演绎为nullptr_t
,所以你可以这样写:
template<typename T> void f(T *ptr); //function to handle non-nullptr argument void f(nullptr_t); //an overload to handle nullptr argument!!!
NULL
定义为#define NULL 0
,所以基本上是int
,这就是为什么f(int)
叫做。C++11介绍nullptr
,它被称为Null
指针常数及其提高类型安全性和解决不明确的情况与现有实现相关的空指针常量不同NUL
。能够理解nullptr
我们首先要明白什么是NULL
与此相关的问题是什么。
NULL
一点儿没错Pre C++11NULL
用于表示没有值的指针或不指向任何有效内容的指针。与流行的观念相反NULL
不是C++中的关键字。它是标准库标头中定义的标识符。总之,你不能用NULL
而不包括一些标准库头
int main() { int *ptr = NULL; return 0; }
产出:
prog.cpp: In function 'int main()': prog.cpp:3:16: error: 'NULL' was not declared in this scope
C++标准将NULL定义为在某些标准库头文件中定义的实现宏。NULL的起源来自C,C++继承了它。C标准将NULL定义为0或(无效)*)0。但是在C++中有一个微妙的区别。
C++不能接受这个规范。与C不同,C++是一种强类型语言。void*
对于任何类型,而C++强制执行显式强制转换),这使得C标准指定的NULL定义在许多C++表达式中毫无用处,例如:
std::string * str = NULL; //Case 1 void (A::*ptrFunc) () = &A::doSomething; if (ptrFunc == NULL) {} //Case 2
如果NULL被定义为(无效)*)0。以上两个表达式都不能工作。
void *
到std::string
...void *
指向成员函数的指针是必需的。因此,与C、C++标准不同,C++标准授权将NULL定义为数字文字0或0L。
NULL
已经开始了?尽管C++标准委员会提出了一个适用于C++的零定义,但这个定义也有其自身的一些问题。NULL对于几乎所有的场景都足够好,但不是全部。对于某些罕见的情况,它给出了令人惊讶和错误的结果。
#include<iostream> void doSomething(int) { std::cout<<"In Int version"; } void doSomething(char *) { std::cout<<"In char* version"; } int main() { doSomething(NULL); return 0; }
产出:
In Int version
很明显,其意图似乎是要调用使用char的版本。*作为参数,但当输出显示作为int版本的函数被调用时。这是因为NULL是一个数字文字。
此外,由于实现定义了NULL可以是0还是0L,因此函数重载解析可能会出现很多混乱。
样本计划:
#include <cstddef> void doSomething(int); void doSomething(char *); int main() { doSomething(static_cast <char *>(0)); // Case 1 doSomething(0); // Case 2 doSomething(NULL) // Case 3 }
分析上面的片段:
doSomething(char *)
如预期doSomething(int)
但也许char*
需要版本是因为0
也是空指针。NULL
定义为0
,,,
打电话doSomething(int)
也许当doSomething(char *)
可能会导致运行时出现逻辑错误。
但是,如果NULL
定义为0L
,,,
调用不明确,导致编译错误。因此,根据实现的不同,相同的代码可以提供不同的结果,这显然是不可取的。当然,C++标准委员会希望纠正这一点,这是nullptr的主要动机。
nullptr
以及如何避免NULL
?C++11引入了一个新的关键字nullptr作为空指针常量。与NULL不同,它的行为不是定义的实现。它不是宏,但它有自己的类型。nullptr有std::nullptr_t
...。C++11适当地定义了nullptr的属性,以避免NULL的缺点。概括一下它的性质:
财产1:它有它自己的类型std::nullptr_t
和
财产2:它是隐式可转换的,可与任何指针类型或指针到成员类型相比较,但是
财产3:它不是隐式可转换的,也不是可与积分类型相比较的,除非bool
...
考虑以下示例:
#include<iostream> void doSomething(int) { std::cout<<"In Int version"; } void doSomething(char *) { std::cout<<"In char* version"; } int main() { char *pc = nullptr; // Case 1 int i = nullptr; // Case 2 bool flag = nullptr; // Case 3 doSomething(nullptr); // Case 4 return 0; }
在上面的节目中,
char *
版本,属性2和3因此,nullptr的引入避免了好的旧空的所有问题。
nullptr
?C++11的经验法则是简单地开始使用nullptr
当你以前使用空的时候。