Ara*_*raK 546 c++ pointers nullptr c++11
我们现在拥有许多新功能的C++ 11.一个有趣且令人困惑的(至少对我来说)是新的nullptr
.
嗯,不再需要令人讨厌的宏了NULL
.
int* x = nullptr;
myclass* obj = nullptr;
Run Code Online (Sandbox Code Playgroud)
尽管如此,我还没有得到如何nullptr
运作.例如,维基百科的文章说:
C++ 11通过引入一个new 关键字作为一个区分空指针常量来解决这个问题:nullptr.它的类型为nullptr_t,它是可隐式转换的,可与任何指针类型或指向成员类型的类型相媲美.除了bool之外,它不可隐式转换或与整数类型相比.
它是一个关键字和一个类型的实例?
另外,你有另一个例子(在维基百科旁边)哪里nullptr
优于好老0
?
Joh*_*itb 384
它是一个关键字和一个类型的实例?
这并不奇怪.这两个true
和false
是关键字和文字他们有一个类型(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
为整型(映射实现定义).A reinterpret_cast
无法转换nullptr_t
为任何指针类型.如果可能,请依靠隐式转换或使用static_cast
.
标准要求sizeof(nullptr_t)
是sizeof(void*)
.
nik*_*nik 57
来自nullptr:一个Type-safe和Clear-Cut Null指针:
新的C++ 09 nullptr关键字指定一个rvalue常量,用作通用空指针文字,替换错误和弱类型的文字0和臭名昭着的NULL宏.因此,nullptr结束了超过30年的尴尬,模棱两可和错误.以下部分介绍了nullptr工具,并展示了如何解决NULL和0的问题.
其他参考:
template
Mot*_*tti 36
当你有一个可以接收指向多个类型的指针的函数时,调用它NULL
是不明确的.现在解决这个问题的方法是接受一个int并假设它是非常hacky 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); }
};
Run Code Online (Sandbox Code Playgroud)
在C++11
你可以重载,nullptr_t
这ptr<T> p(42);
将是一个编译时错误而不是运行时assert
.
ptr(std::nullptr_t) : p_(nullptr) { }
Run Code Online (Sandbox Code Playgroud)
Gab*_*les 30
C++专家Alex Allain在这里完美地说:
"...想象你有以下两个函数声明:
void func(int n);
void func(char *s);
func( NULL ); // guess which function gets called?
Run Code Online (Sandbox Code Playgroud)
虽然它看起来像第二个函数将被调用 - 毕竟,你传递的似乎是一个指针 - 它实际上是第一个被调用的函数!麻烦的是因为NULL是0,而0是一个整数,所以将调用第一个版本的func.这是一种事情,是的,不会一直发生,但是当它确实发生时,是非常令人沮丧和困惑的.如果您不知道发生了什么的细节,它可能看起来像编译器错误.看起来像编译器错误的语言功能,不是你想要的.
输入nullptr.在C++ 11中,nullptr是一个新的关键字,可以(并且应该!)用于表示NULL指针; 换句话说,无论你以前写过NULL,都应该使用nullptr.对于程序员来说,你不再清楚(每个人都知道NULL意味着什么),但它对编译器来说更加明确,当用作指针时,编译器将不会再看到任何地方被用来具有特殊含义的0."
nullptr
不能分配给int
诸如int之类但只能分配类型int *ptr
; 要么是内置的指针类型,std::shared_ptr<T>
要么是智能指针等NULL
我相信这是一个重要的区别,因为NULL
仍然可以分配到一个0
和int
作为nullptr
是一个宏扩展到了int
它可以作为一个既初始值int *ptr
以及一个std::shared_ptr<T>
.
好吧,其他语言也保留了作为类型实例的保留字。例如,Python:
>>> None = 5
File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>
Run Code Online (Sandbox Code Playgroud)
实际上,这是一个相当接近的比较,因为None
通常将其用于尚未初始化的事物,但与此同时,诸如None == 0
false之类的比较也是如此。
另一方面,在纯C中, NULL == 0
将返回true IIRC,因为NULL
只是一个返回0的宏,它始终是无效地址(AFAIK)。
另外,您是否还有另一个示例(除了Wikipedia之外)
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;
}
Run Code Online (Sandbox Code Playgroud)
它产生以下输出:
(a == pb): 1
(a == 0): 0
(a == NULL): 0
(a == null): 1
Run Code Online (Sandbox Code Playgroud)
小智 5
让我首先给你一个简单的实现nullptr_t
struct nullptr_t \n{\n void operator&() const = delete; // Can\'t take address of nullptr\n\n template<class T>\n inline operator T*() const { return 0; }\n\n template<class C, class T>\n inline operator T C::*() const { return 0; }\n};\n\nnullptr_t nullptr;\n
Run Code Online (Sandbox Code Playgroud)\nnullptr
是返回类型解析器习惯用法的一个微妙示例,它根据分配给它的实例的类型自动推断出正确类型的空指针。
int *ptr = nullptr; // OK\nvoid (C::*method_ptr)() = nullptr; // OK\n
Run Code Online (Sandbox Code Playgroud)\nnullptr
将 分配给整数指针时,int
将创建模板化转换函数的类型实例化。方法指针也是如此。nullptr
是值为零的整数文字,因此您无法使用我们通过删除 & 运算符来完成的地址。nullptr
首先我们为什么需要?NULL
有一些问题,如下所示:char *str = NULL; // Implicit conversion from void * to char *\nint i = NULL; // OK, but `i` is not pointer type\n
Run Code Online (Sandbox Code Playgroud)\nvoid func(int) {}\nvoid func(int*){}\nvoid func(bool){}\n\nfunc(NULL); // Which one to call?\n
Run Code Online (Sandbox Code Playgroud)\nerror: call to \'func\' is ambiguous\n func(NULL);\n ^~~~\nnote: candidate function void func(bool){}\n ^\nnote: candidate function void func(int*){}\n ^\nnote: candidate function void func(int){}\n ^\n1 error generated.\ncompiler exit status 1\n
Run Code Online (Sandbox Code Playgroud)\nstruct String\n{\n String(uint32_t) { /* size of string */ }\n String(const char*) { /* string */ }\n};\n\nString s1( NULL );\nString s2( 5 );\n
Run Code Online (Sandbox Code Playgroud)\nString s((char*)0))
.