C++中空指针的值是0。C++98, C++03, C++11, C++14, C++17... 永远也不会改变这个知识点。
例如: char* p=0; //很直白,p没有指向任何地址。
但是0是个文字量,没有携带类型信息。
void foo(int);
void foo(char*);
foo(0); //根据直觉,好像应该调用foo(int),实际也是如此。
0和空指针的关系是:空指针的值是0;而0不一定是空指针(还可能是整数0)
C语言中,有一个很明确的空指针NULL。其定义为#define NULL ((void*)0)。在C语言里,NULL和0有着本质区别,NULL是有类型的(void*)!
C语言里,NULL和空指针的关系是:空指针的值是NULL,而NULL就是空指针。
foo(NULL); //C语言角度看这句话,根据直觉,NULL是空指针,应调用void foo(char*);,实际也是如此。
foo(0); //C语言角度看这句话,根据直觉,应调用void foo(int);,实际也是如此。
C++出现后,情况有了恶化。在C++语言中NULL被定义成0,而不是((void*)0)
因为 char* p = ((void*)0); 在C++中编译不过去,C++禁止void*隐式转换成其它指针,C++认为这是pitfall,是陷阱。不能为了一点小利而饮鸩止渴。
foo(NULL); //C++语言角度看这句话,宏展开是foo(0),实际调用foo(int),完全不符合直觉,按照C语言习惯思考的程序员将可能遇到一个大BUG。
没有吃过亏人的,自然对NULL这个东西无所谓,吃过亏的人自然对NULL很不爽。因此要寻求完善,寻求改进。
虽然在字面上NULL能提示程序员们这是空指针,但是对计算机编译器,NULL与整数0没什么区别。编译器不知道NULL是空指针!!!!!
C++引入nullptr表示空指针,这是一个一等类的一个全局对象,占有存储空间,有自己的身份类型nullptr_t。
foo(nullptr); //现在,调用foo(char*),直觉完全符合实际!!
nullptr有个神奇的功能,它能转换为任何类型的空指针。
char* p1 = nullptr; //好像是执行这句 char* p1 = (char*)0;
std::vector
其实只是用了简单的模板成员函数,利用了模板的一点小威力。
class nullptr_t
{
public:
template<typename T> operator T*() const { return (T*)0; }
} ;
为什么不需要在使用nullptr时,引入对应的头文件呢?
显然C++编译器已经预置支持nullptr_t类型和null_ptr全局对象了。
相似的现象还有std::initializer_list,也是从语言层面引入的一个C++一等类型。