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

不需要讨厌的宏NULL了。

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

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

c++ 11通过引入一个新的关键字作为区分空指针常量nullptr来纠正这一点。它的类型为nullptr_t,可隐式转换,可与任何指针类型或指针到成员类型相比较。它不能隐式转换,也不能与整型相比,bool类型除外。

它如何既是关键字又是类型的实例?

此外,你是否有另一个例子(除了维基百科的一个),其中nullptr优于好旧的0?


当前回答

Nullptr不能赋值给整型类型,比如int型,只能赋值给指针类型;内置指针类型,如int *ptr或智能指针,如std::shared_ptr<T>

我相信这是一个重要的区别,因为NULL仍然可以被赋给整型和指针,因为NULL是一个扩展到0的宏,可以作为int的初始值以及指针。

其他回答

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

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

这实际上是一个相当接近的比较,因为None通常用于尚未初始化的东西,但与此同时,像None == 0这样的比较是假的。

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

此外,你是否有另一个例子(除了维基百科的一个),其中nullptr优于好旧的0?

是的。这也是在我们的生产代码中出现的一个(简化的)真实例子。它之所以突出,是因为gcc能够在交叉编译到具有不同寄存器宽度的平台时发出警告(仍然不确定为什么只有在从x86_64交叉编译到x86时,警告警告:从NULL转换为非指针类型'int'):

考虑以下代码(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

NULL need not to be 0. As long you use always NULL and never 0, NULL can be any value. Asuming you programme a von Neuman Microcontroller with flat memory, that has its interrupt vektors at 0. If NULL is 0 and something writes at a NULL Pointer the Microcontroller crashes. If NULL is lets say 1024 and at 1024 there is a reserved variable, the write won't crash it, and you can detect NULL Pointer assignments from inside the programme. This is Pointless on PCs, but for space probes, military or medical equipment it is important not to crash.

为什么在c++ 11中使用nullptr ?是什么?为什么NULL是不充分的?

c++专家Alex Allain在这里说得很好(我用粗体加了重点):

...imagine you have the following two function declarations: void func(int n); void func(char *s); func( NULL ); // guess which function gets called? Although it looks like the second function will be called--you are, after all, passing in what seems to be a pointer--it's really the first function that will be called! The trouble is that because NULL is 0, and 0 is an integer, the first version of func will be called instead. This is the kind of thing that, yes, doesn't happen all the time, but when it does happen, is extremely frustrating and confusing. If you didn't know the details of what is going on, it might well look like a compiler bug. A language feature that looks like a compiler bug is, well, not something you want. Enter nullptr. In C++11, nullptr is a new keyword that can (and should!) be used to represent NULL pointers; in other words, wherever you were writing NULL before, you should use nullptr instead. It's no more clear to you, the programmer, (everyone knows what NULL means), but it's more explicit to the compiler, which will no longer see 0s everywhere being used to have special meaning when used as a pointer.

Allain在文章结尾写道:

不管这些——c++ 11的经验法则是,只要在过去使用NULL,就开始使用nullptr。

(我的话):

最后,不要忘记nullptr是一个对象——一个类。它可以在任何之前使用NULL的地方使用,但如果你因为某种原因需要它的类型,它的类型可以用decltype(nullptr)提取,或者直接描述为std::nullptr_t,这只是一个decltype(nullptr)的类型定义,如下所示:

定义在头<cstddef>:

See:

https://en.cppreference.com/w/cpp/types/nullptr_t 和https://en.cppreference.com/w/cpp/header/cstddef

namespace std
{
typedef decltype(nullptr) nullptr_t; // (since C++11)
// OR (same thing, but using the C++ keyword `using` instead of the C and C++ 
// keyword `typedef`):
using nullptr_t = decltype(nullptr); // (since C++11)
} // namespace std

引用:

c++ 11中更好的类型- nullptr,枚举类(强类型枚举)和cstdint https://en.cppreference.com/w/cpp/language/decltype https://en.cppreference.com/w/cpp/types/nullptr_t https://en.cppreference.com/w/cpp/header/cstddef https://en.cppreference.com/w/cpp/keyword/using https://en.cppreference.com/w/cpp/keyword/typedef

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

2.14.7指针字面量[lex.nullptr] pointer-literal: nullptr 指针字面值是关键字nullptr。它是std::nullptr_t类型的右值。

它很有用,因为它没有隐式地转换成一个整数值。