ein*_*ica 9 c c++ cross-language null-pointer nullptr
我已经编写 C++ 多年,nullptr用于空指针。我也知道 C,从那里 NULL 起源,并记住它是一个空指针的常量,类型void *。
出于NULL某些原因,我不得不在我的 C++ 代码中使用某些东西。好吧,想象一下当在一些模板参数推导过程中编译器告诉我我的 NULL 真的是一个......长时我的惊讶。所以,我仔细检查了:
#include <type_traits>
#include <cstddef>
static_assert(not std::is_same<decltype(NULL), long>::value, "NULL is long ???");
事实上,静态断言失败(使用 GCC 和 clang)。
在cppreference.com 上检查,果然(C++11 措辞):
宏 NULL 是一个实现定义的空指针常量,它可以是一个值为 0 的整数文字,或者一个类型为 的纯右值
std::nullptr_t。
为什么这是有道理的?就其本身而言,鉴于 C 的不兼容性?
Nic*_*las 14
在 C 中, avoid*可以隐式转换为 any T*。因此,制作NULL一个void*是完全合适的。
但这非常危险。因此,C++ 取消了这种转换,要求您手动执行大多数指针转换。但这会导致与 C 的源代码不兼容;使用NULLC 想要的方式的有效 C 程序将无法在 C++ 中编译。它还需要一堆冗余:T *pt = (T*)(NULL);,这将是令人讨厌和毫无意义的。
所以 C++ 将NULL宏重新定义为整型字面量 0。在 C 中,字面量 0 也可以隐式转换为任何指针类型并生成空指针值,C++ 保留了这种行为。
当然,现在对空指针常量使用文字 0(或更准确地说,值为 0 的整数常量表达式)不是最好的主意。特别是在允许重载的语言中。因此,C++11 在一个关键字上完全使用 NULL,该关键字专门表示“空指针常量”,仅此而已。
Tob*_*ght 12
在这两种语言中,NULL是实现定义的空指针常量。C++第17.2.3节,其定义参考C 7.19。
也就是说,在C中,NULL可以定义为整数类型或者为类型void*,而在C++中可以定义为整数类型;nullptr_t如果我正确解释了标准,它也可以被定义为 a 。隐藏的(非规范的)脚注表明这(void*)0不可能是有效的定义,这是有道理的,因为 C++ 没有 Cvoid*到其他指针类型的隐式转换。
如果您有一个将其定义为 的 C 编译器((void*)0)和一个将其定义为 的 C++ 编译器0L,则它们都是一致的。两种实现都满足用例(可以从 分配并与 进行比较NULL)。
C++ 的引入nullptr主要是为了提供适合重载的类型值,因为传递NULL给函数可以选择整数版本被认为是令人惊讶的。
我的假设始终是,实现的决定保留NULLas0是与 C++98 向后兼容的问题。我见过很多在非指针上下文中使用的代码NULL,特别是作为(可能是无意的,或者至少是无知的)数组中空终止符的替代品。由于自 '11 以来的最佳实践是“NULL根本不使用”,因此重新定义NULLtonullptr可能会破坏坏/旧代码,而对好/新代码几乎没有帮助。