c - 究竟什么是nullptr?

  显示原文与译文双语对照的内容

我们现在拥有了 C++11,有许多新特性。 一个有趣而令人困惑的( 至少对于我来说) 是新的nullptr

好了,对于令人讨厌的宏 NULL 不再需要了。


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

但是,我还是不明白 nullptr 是如何工作的。 例如,维基百科文章说:

C++11通过引入一个新的关键字作为可以分辨空指针常量来更正这里问题: nullptr。的类型nullptr_t,隐式转换,与任何指针类型或pointer-to-member类型。 它不是隐式可以转换的或者与整型可以比的,除了布尔类型。

它是关键字的关键字和类型的实例?

另外,你还有另一个示例( 在维基百科旁边),其中 nullptr 优于旧的0

时间:

它是关键字的关键字和类型的实例?

这不足为奇。truefalse 都是关键字,并且它们是一个类型( bool ) 。 nullptr 是指针文字 std::nullptr_t 类型,它是一个 prvalue ( 不能使用 &的地址) 。

  • 4.10 关于类型的指针转换说 prvalue std::nullptr_t 是一个空指针常量,这不可或缺的空指针常量可以转换为 std::nullptr_t 。 不允许相反方向。 这允许重载指针和整数的函数,并通过 nullptr 来选择指针版本。 通过 NULL 或者 0 会迷惑选择 int 版本。

  • nullptr_t 到整型的转换需要一个 reinterpret_cast,并且具有与 (void*)0 到整型( 映射实现已经定义) 相同的语义。 reinterpret_cast 无法将 nullptr_t 转换为任何指针类型。 如果可能或者使用 static_cast,依赖于隐式转换。

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

nullptr: Type-safe和明确的空指针 :

新C++09nullptr关键字指定一个右值常数作为一个普遍的空指针文字,替换车和weakly-typed文字 0臭名昭著的空宏。 nullptr因此结束了 30年上的尴尬,模糊和 Bug 。 以下各节介绍了nullptr工具,并展示了如何弥补空和 0的缺陷。

其他引用:

当你有一个可以接收指向多个类型的指针的函数,然后用 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++0x 中,你可以重载 nullptr_t,使 ptr<T> p(42); 成为compile-time错误而不是 run-time assert


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

其他语言有保留的单词,它们是类型的实例。 python,例如:


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

这实际上是比较接近的比较,因为 None 通常用于还没有初始化的东西,但同时比较像 None == 0 一样。

另一方面,在纯C 中,NULL == 0 会 return true IIRC,因为 NULL 只是一个返回 0的宏,它总是一个无效的地址( AFAIK ) 。

这是关键字,因为标准将把它指定为。 ;- ) 根据最新的公共草案( n2914 )

2.14.7 指针文本 [lex.nullptr ]


pointer-literal:
nullptr

指针文本是关键字 nullptr 。 它是类型 std::nullptr_t的右值。

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

nullptr 不能被分配给 integral type,比如 int,但只能是一个类型 pointer ;一个内置指针类型,比如 int *ptr 或者一个智能指针例如 std::shared_ptr<T>

我认为这是一个重要的区别,因为 NULL 仍然可以被分配到 integral typepointer,因为 NULL 是一个扩展到 0的宏,既可以作为 int,也可以作为一个 pointer

另外,你还有另一个示例( 在维基百科旁边),其中 nullptr 优于旧的0?

是的,它也是一个在我们的生产代码中发生的( 简化) 真实的例子。 只站着,因为gcc能够发出警告当crosscompiling平台不同的寄存器的宽度(仍然不确定为什么只有当 crosscompiling x86_64x86,警告说 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

...