1.nullprt与NULL
代码:
void f(int i) {
cout << "f(int)" << endl;
}
void f(char* c) {
cout << "f(char*)" << endl;
}
int main () { f(0); f('\0'); // f(NULL); 在我的GCC中编译不过,因为NULL被认为是(void*)0,二义性 // f((void*)0); 二义性 f(nullptr); return 0; }
结果:
因为NULL容易出问题,因此出现了nullptr。nullptr是有类型的,并且可以被隐式转化为指针类型。
额外:NULL,0,'\0' 的区别
NULL在 "stdio.h" 中的定义如下:
#ifndef __cplusplus
#define NULL ((void *)0) #else /* C++ */ #define NULL 0 #endif /* C++ */
说明NULL在C中是(void*)0,而在C++中是0.
注意:0对于指针来说是一个特别对待的值,"当常量0处于应该作为指针使用的上下文中时,它就作为空指针使用“
如下程序所示;
int main () { void* p; p = 0; //p = 1; 这里报错了,虽然与0都是int类型 cout << p << endl; return 0; }
而'\0'是所有位都是0的字节,在ASCII码表中所示如下:
表明'\0'的二进制值是0000 0000
有趣的情况:C的字符串是用'\0'结尾的,而有的系统(比如Ubuntu14.04)用NULL也能结束(不过这在其他系统不一定能行得通):
int main () { char str[3]; str[0] = 'a'; str[1] = 'b'; cout << str << endl; str[2] = '\0'; cout << str << endl; str[2] = 0; cout << str << endl; return 0; }
结果:
这三个都是表现出0,但是你的0不是我的0,如下代码:
int main () { cout << "\\0的大小: " << sizeof('\0') << endl; cout << "0的大小: " << sizeof(0) << endl; cout << "NULL的大小:" << sizeof(NULL) << endl; return 0; }
结果:
总:这三者都是零,但是NULL是16进制的0(对于C来说这是(void*)0,是指针),0是10进制的0,'\0'是8进制的0
PS:上面NULL可以替代'\0'的情况可以理解为,在二进制中,NULL是16个0而'\0'是8个0,NULL可以截断最后8位成为'\0'。
2.nullptr是关键字
3.nullptr的类型是nullptr_t
使用nullptr_t需要包含<cstddef>,其定义为typedef decltype(nullptr) nullptr_t;
使用nullptr_t可以定义多个指针空值,而不仅仅是nullptr一个(虽然nullptr已经够用了)
int main () { nullptr_t myNull; f(myNull); return 0; }
规则:
4.nullptr与模板
模板只把nullptr作为一个普通的类型进行推导(并不会视为T* 指针)
template<typename T> void g(T* t) { cout << sizeof(T) << endl;} template<typename T> void h(T t) { cout << sizeof(T) << endl;} int main () { // g(nullptr); 类型是nullptr_t而不是指针 g((char*)0); g((int*)nullptr); h(0); h(nullptr); h((int*)nullptr); return 0; }
5.规定sizeof(nullptr_t) == sizeof(void*)
nullptr是一个编译时期的常量,是编译时期的关键字,能被编译器识别。(void*)0需要经过类型转换才能变成其他指针类型。
6.nullprt地址
代码:
int main () { nullptr_t my_null; cout << &my_null << endl; //可以打印nullptr_t的地址 // cout << nullptr << endl; 错误 const nullptr_t &nullptr_r = nullptr; //可以打印nullptr的右值引用地址 cout << &nullptr_r << endl; return 0; }
参考书籍:《深入理解C++11》