什么是nullptr?

我们现在拥有许多新function的C ++ 11。 一个有趣和令人困惑的(至less对我来说)是新的nullptr

好了,再也不需要讨厌的macrosNULL

 int* x = nullptr; myclass* obj = nullptr; 

不过,我没有得到如何nullptr作品。 例如, 维基百科文章说:

C ++ 11通过引入一个新的关键字来作为一个可区分的空指针常量来纠正这个问题:nullptr。 它的types是nullptr_t ,它可以隐式转换,并且可以和任何指针types或成员指针types进行比较。 除了bool之外,它不是可以转换的,也不可以与整数types相比较。

它是怎样的一个关键字和一个types的实例?

另外,你是否还有另外一个例子(维基百科之外), nullptr优于0

它是怎样的一个关键字和一个types的实例?

这并不奇怪。 truefalse都是关键字,而文字是文字( bool )。 nullptrstd::nullptr_ttypes的指针字面值 ,它是一个prvalue(你不能用&来取它的地址)。

  • 4.10关于指针转换说std::nullptr_ttypes的prvalue是一个空指针常量,并且一个整型空指针常量可以转换为std::nullptr_t 。 相反的方向是不允许的。 这允许为指针和整数重载一个函数,并且传递nullptr来select指针的版本。 传递NULL0会混淆selectint版本。

  • nullptr_t转换为整数types需要reinterpret_cast ,并且具有与(void*)0types转换(定义的映射实现)相同的语义。 reinterpret_cast无法将nullptr_t转换为任何指针types。 依靠隐式转换(如果可能)或使用static_cast

  • 标准要求sizeof(nullptr_t)sizeof(void*)

来自nullptr:types安全且清除空指针

新的C ++ 09 nullptr关键字指定一个rvalue常量,用作通用的空指针字面值,replacebug和弱types文字0和臭名昭着的NULLmacros。 nullptr因此结束了30多年的尴尬,模棱两可和错误。 以下部分介绍了nullptr工​​具,并展示了它如何纠正NULL和0的疾病。

其他参考:

  • 带有示例代码的WikiBooks 。
  • 在堆栈溢出: 你在C ++中使用NULL或0(零)指针?
  • template
  • Google group: comp.lang.c ++。moderated – 编译器讨论

当你有一个函数可以接收指向多个types的指针时,用NULL调用它是不明确的,现在这种方法是非常冒险的,接受一个int并假定它是NULL

 template <class T> class ptr { T* p_; public: ptr(T* p) : p_(p) {} template <class U> ptr(U* u) : p_(dynamic_cast<T*>(u)) { } // Without this ptr<T> p(NULL) would be ambiguous ptr(int null) : p_(NULL) { assert(null == NULL); } }; 

C++11你可以在nullptr_t上重载,这样ptr<T> p(42); 将是编译时错误,而不是运行时assert

 ptr(std::nullptr_t) : p_(nullptr) { } 

nullptr不能被分配给一个integral type比如一个int,而只能是一个typespointer ; 内build的指针types(如int *ptr或智能指针(如std::shared_ptr<T>

我相信这是一个重要的区别,因为NULL仍然可以分配给一个integral type和一个pointer因为NULL是一个扩展为0的macros,既可以作为int的初始值,也可以作为pointer

这是一个关键字,因为标准将这样指定。 ;-)根据最新的公众草案(n2914)

2.14.7指针文字[lex.nullptr]

 pointer-literal: nullptr 

指针文字是关键字nullptr 。 它是std::nullptr_ttypes的右值。

这很有用,因为它不会隐式转换为整数值。

那么,其他语言已经保留的字是types的实例。 Python,例如:

 >>> None = 5 File "<stdin>", line 1 SyntaxError: assignment to None >>> type(None) <type 'NoneType'> 

这实际上是一个相当接近的比较,因为None通常用于没有初始化的东西,但同时比较如None == 0是错误的。

另一方面,在普通的C中, NULL == 0将返回真正的IIRC,因为NULL只是一个返回0的macros,这个macros总是一个无效地址(AFAIK)。

另外,你是否还有另外一个例子(维基百科之外), nullptr优于0?

是。 这也是我们生产代码中出现的一个(简化的)真实世界的例子。 这只是因为gcc能够在交叉编译到具有不同寄存器宽度的平台时发出警告(仍然不确定为什么只有在从x86_64到x86的交叉编译时警告warning: converting to non-pointer type 'int' from NULL ) :

考虑这个代码(C ++ 03):

 #include <iostream> struct B {}; struct A { operator B*() {return 0;} operator bool() {return true;} }; int main() { A a; B* pb = 0; typedef void* null_ptr_t; null_ptr_t null = 0; std::cout << "(a == pb): " << (a == pb) << std::endl; std::cout << "(a == 0): " << (a == 0) << std::endl; // no warning std::cout << "(a == NULL): " << (a == NULL) << std::endl; // warns sometimes std::cout << "(a == null): " << (a == null) << std::endl; } 

它产生这个输出:

 (a == pb): 1 (a == 0): 0 (a == NULL): 0 (a == null): 1 

假设你有一个被重载的函数(f)来取int和char *。 在C ++ 11之前,如果你想用一个空指针来调用它,而你使用了NULL(即值为0),那么你可以调用一个为int重载的指针:

 void f(int); void f(char*); void g() { f(0); //calls f(int) } 

这可能不是你想要的。 C ++ 11用nullptr解决了这个问题; 现在你可以写下面的内容:

 void g() { f(nullptr); //calls f(char*) } 

NULL不必为0.只要你总是使用NULL而不是0,NULL可以是任何值。 假设你编程一个具有平坦内存的冯·诺依曼微控制器,它的中断向量为0.如果NULL为0,并且在NULL指针处写入,则微控制器崩溃。 如果NULL是可以说1024和1024在这里有一个保留的variables,写入不会崩溃它,你可以从程序内部检测NULL指针分配。 这在PC上是毫无意义的,但对于太空探测器,军事或医疗设备来说,重要的是不要撞毁。