Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是nullptr?_C++_Pointers_C++11_Nullptr - Fatal编程技术网

C++ 什么是nullptr?

C++ 什么是nullptr?,c++,pointers,c++11,nullptr,C++,Pointers,C++11,Nullptr,我们现在有了具有许多新特性的C++11。一个有趣且令人困惑的(至少对我来说)是新的nullptr 嗯,不再需要讨厌的宏NULL int* x = nullptr; myclass* obj = nullptr; template <class T> class ptr { T* p_; public: ptr(T* p) : p_(p) {} template <class U> ptr(U* u) :

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

嗯,不再需要讨厌的宏
NULL

int* x = nullptr;
myclass* obj = nullptr;
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); }
};
不过,我还是不明白
nullptr
是如何工作的。例如,他说:

C++11通过引入一个新的关键字作为一个可区分的空指针常量:nullptr来纠正这个问题。它属于类型nullptr\u t,可隐式转换,并可与任何指针类型或指向成员的指针类型进行比较。除了bool之外,它不能隐式转换,也不能与整型进行比较

它如何成为一个关键字和一个类型的实例


另外,你有没有另一个例子(除了维基百科的例子)说明
nullptr
优于旧的
0

好吧,其他语言都有作为类型实例的保留字。例如,Python:

>>> None = 5
  File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>
>无=5
文件“”,第1行
SyntaxError:分配给None
>>>类型(无)
这实际上是一个相当接近的比较,因为
None
通常用于未初始化的内容,但同时
None==0
等比较是错误的


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

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

2.14.7指针文字[lex.nullptr]

pointer-literal:
nullptr
指针文本是关键字
nullptr
。它是类型为
std::nullptr\u t
的右值

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

来自:

新的C++09 nullptr关键字指定了一个用作通用空指针文本的右值常量,替换了有缺陷的弱类型文本0和臭名昭著的空宏。nullptr因此结束了30多年的尴尬、模糊和错误。以下各节介绍了nullptr功能,并展示了它如何解决NULL和0的问题

其他参考资料:

  • ,带有示例代码
  • 在堆栈溢出处:
  • 谷歌集团:
它如何成为一个关键字和一个类型的实例

这并不奇怪。
true
false
都是关键字,它们作为文本有一个类型(
bool
nullptr
是一个类型为
std::nullptr\u t
的指针文本,它是一个PR值(不能使用
获取它的地址)

  • 4.10
    关于指针转换说明类型为
    std::nullptr\u t
    的prvalue是一个空指针常量,整型空指针常量可以转换为
    std::nullptr\u t
    。不允许相反方向。这允许为指针和整数重载函数,并传递
    nullptr
    以选择指针版本。传递
    NULL
    0
    会混淆地选择
    int
    版本

  • nullptr\u t
    强制转换为整数类型需要
    重新解释强制转换
    ,并且与将
    (void*)0
    强制转换为整数类型(定义了映射实现)具有相同的语义。
    reinterpret\u cast
    无法将
    nullptr\u t
    转换为任何指针类型。如果可能,请依赖隐式转换或使用
    静态\u cast

  • 该标准要求
    sizeof(nullptr\t)
    be
    sizeof(void*)


当您有一个函数可以接收指向多个类型的指针时,使用
NULL
调用它是不明确的。通过接受int并假设它是
NULL
,现在解决这个问题的方法非常粗糙

int* x = nullptr;
myclass* obj = nullptr;
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); }
};

nullptr
不能分配给整数类型,例如
int
,而只能分配给指针类型;内置指针类型,如
int*ptr
,或智能指针,如
std::shared\u ptr

我认为这是一个重要的区别,因为
NULL
仍然可以分配给整型和指针,因为
NULL
是一个扩展到
0
的宏,它既可以作为
int
的初始值,也可以作为指针

另外,你有没有另一个例子(除了维基百科的例子)说明
nullptr
优于旧的0

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

考虑以下代码(C++03):


NULL不必为0。只要使用always NULL和never 0,NULL可以是任何值。你可以编程一个冯·诺依曼微控制器,它有一个平面存储器,它的中断向量为0。如果NULL为0,并且有东西在NULL指针处写入,则微控制器崩溃。如果NULL为1024,并且在1024处有一个保留变量,则写入操作不会使其崩溃,并且您可以从程序内部检测NULL指针分配。这在个人电脑上是没有意义的,但对于太空探测器、军事或医疗设备来说,重要的是不要崩溃。

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

的重载。
void f(int);
void f(char*);

void g() 
{
  f(0); // Calls f(int).
  f(NULL); // Equals to f(0). Calls f(int).
}
这可能不是你想要的。C++11使用nullptr解决了这个问题;现在您可以编写以下内容:

void g()
{
  f(nullptr); //calls f(char*)
}
为什么在C++11中使用空ptr?这是怎么一回事?为什么空值是不够的? C++专家(我的重点用粗体加上):

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

void func(int n); 
void func(char *s);

func( NULL ); // guess which function gets called?
struct nullptr_t 
{
    void operator&() const = delete;  // Can't take address of nullptr

    template<class T>
    inline operator T*() const { return 0; }

    template<class C, class T>
    inline operator T C::*() const { return 0; }
};

nullptr_t nullptr;
int *ptr = nullptr;                // OK
void (C::*method_ptr)() = nullptr; // OK
char *str = NULL; // Implicit conversion from void * to char *
int i = NULL;     // OK, but `i` is not pointer type

void func(int) {}
void func(int*){}
void func(bool){}

func(NULL);     // Which one to call?

error: call to 'func' is ambiguous
    func(NULL);
    ^~~~
note: candidate function void func(bool){}
                              ^
note: candidate function void func(int*){}
                              ^
note: candidate function void func(int){}
                              ^
1 error generated.
compiler exit status 1

struct String
{
    String(uint32_t)    {   /* size of string */    }
    String(const char*) {       /* string */        }
};

String s1( NULL );
String s2( 5 );

#define NULL 0
int i = NULL;     //OK
int i = nullptr;  //error
int* p = NULL;    //OK
int* p = nullptr; //OK
void func(int x);   //1)
void func(int* x);  //2)
auto result = findRecord( /* arguments */ );

if (result == nullptr)
{
 ...
}
template<typename T>
void func(T *ptr)
{
    ...
}
func(nullptr);