1、NULL和0
-  在C语言标准定义中, NULL的定义为(void *)0这样的代码意味着可以进行强制类型转换一个 void *类型的指针到任意类型的指针#define NULL (void*)0 char *p = NULL;
-  C++11之后 NULL被定义为0,此时可以认为NULL不完全是一个空指针。#ifndef __cplusplus #define NULL ((void *)0) #else /* C++ */ #define NULL 0 #endif /* C++ */-  C++是一门类型安全的语言,*无法将一个void 类型的指针隐式转换为其他类型 char *p = 0; char *p1 = NULL; char *p2 = (void *)0; // 报错 char *p3 = reinterpret_cast<char*>(NULL); // 强转可以
-  而这样又会引入另外一个重载的二义性问题 因为NULL的值实际是0,但是 char也可以接收一个NULL(0)值,但是NULL又被定义为0值,这样就会导致一个二义性问题。void func(int ) {std::cout << "func(int)" << std::endl; } void func(char *) {std::cout << "func(char *) " << std::endl; }void test1() {func(0); // 调用func(int) // func(NULL); // 报错func(reinterpret_cast<char *>(NULL)); //强转可以调用func(char *) }
 
-  
2、nullptr
-  为了解决上面带来的二义性问题,C++11之后引入了 nullptr来专门区分0和空指针。
-  nullptr的类型为std::nullptr_t,nullptr是一个std::nullptr_t的纯右值
-  nullptr能够隐式的转换为任何指针,因此空指针的时候推荐使用nullptr
-  而通过 nullptr就可以解决上面的二义性问题void test2() {func(0); // 调用func(int)func(nullptr); // 调用func(char *) }
3、nullptr_t的定义
- 可以看到nullptr被定义为nullptr_t类型
- 同时nullptr_t的类型长度与void *长度相同
namespace std
{typedef __SIZE_TYPE__ 	size_t;typedef __PTRDIFF_TYPE__	ptrdiff_t;#if __cplusplus >= 201103Ltypedef decltype(nullptr)	nullptr_t;
#endif
}
static_assert(sizeof(std::nullptr_t) == sizeof(void *));
- 而nullptr_t也可以定义一个其他指针的空指针对象并且与nullptr有相同的能力,而且被创建的对象是一个左值
void test3()
{std::nullptr_t null1;std::nullptr_t null2;std::cout << "&null1 = " << &null1 << std::endl;std::cout << "&null2 = " << &null2 << std::endl;
//    std::cout << "&nullptr = " << &nullptr << std::endl;            //报错,右值没有地址
}