51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

指针空值类型 - nullptr


配套视频课程已更新完毕,大家可通过以下两种方式观看视频讲解:

关注公众号:爱编程的大丙,或者进入大丙课堂学习。


在C++程序开发中,为了提高程序的健壮性,一般会在定义指针的同时完成初始化操作,或者在指针的指向尚未明确的情况下,都会给指针初始化为NULL,避免产生野指针(没有明确指向的指针,操作也这种指针极可能导致程序发生异常)。C++98/03 标准中,将一个指针初始化为空指针的方式有 2 种:

|-------------|------------------------------------------| | 1 2 | char *ptr = 0; char *ptr = NULL; |

在底层源码中NULL这个宏是这样定义的:

|-----------------------|-----------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 | #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif |

也就是说如果源码是C++程序NULL就是0,如果是C程序NULL表示(void*)0。那么为什么要这样做呢? 是由于 C++ 中,void * 类型无法隐式转换为其他类型的指针,此时使用 0 代替 ((void *)0),用于解决空指针的问题。这个0(0x0000 0000)表示的就是虚拟地址空间中的0地址,这块地址是只读的。 虚拟地址空间结构图

C++ 中将 NULL 定义为字面常量 0,并不能保证在所有场景下都能很好的工作,比如,函数重载时,NULL0 无法区分:

|------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> using namespace std; void func(char *p) { cout << "void func(char *p)" << endl; } void func(int p) { cout << "void func(int p)" << endl; } int main() { func(NULL); // 想要调用重载函数 void func(char *p) func(250); // 想要调用重载函数 void func(int p) return 0; } |

测试代码打印的结果为:

|-------------|-------------------------------------------| | 1 2 | void func(int p) void func(int p) |

通过打印的结果可以看到,虽然调用func(NULL);最终链接到的还是void func(int p)和预期是不一样的,其实这个原因前边已经说的很明白了,在C++中NULL0是等价的。

出于兼容性的考虑,C++11 标准并没有对 NULL 的宏定义做任何修改,而是另其炉灶,引入了一个新的关键字nullptrnullptr 专用于初始化空类型指针,不同类型的指针变量都可以使用 nullptr 来初始化

|---------------|---------------------------------------------------------------------------------| | 1 2 3 | int* ptr1 = nullptr; char* ptr2 = nullptr; double* ptr3 = nullptr; |

对应上面的代码编译器会分别将 nullptr 隐式转换成int*char* 以及 double* 指针类型。

使用nullptr可以很完美的解决上边提到的函数重载问题:

|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <iostream> using namespace std; void func(char *p) { cout << "void func(char *p)" << endl; } void func(int p) { cout << "void func(int p)" << endl; } int main() { func(nullptr); func(250); return 0; } |

测试代码输出的结果:

|-------------|---------------------------------------------| | 1 2 | void func(char *p) void func(int p) |

通过输出的结果可以看出,nullptr 无法隐式转换为整形,但是可以隐式匹配指针类型。在 C++11 标准下,相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮。

赞(0)
未经允许不得转载:工具盒子 » 指针空值类型 - nullptr