ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ 笔记(28)— C++ 中 NULL和 nullptr 的区别

2021-05-15 23:30:35  阅读:167  来源: 互联网

标签:null 28 void nullptr C++ NULL pointer 指针


最近看公司代码的时候发现在判断指针是否为空的时候,有的时候用的是 NULL, 有的时候用的是 nullptr 感觉很奇怪,好奇心驱使我查了下两者的区别,发现还是有很多细节需要学习的。

1. NULL 在 C/C++ 中的定义

先来看下 C99 是怎么定义 NULL 的:

NULL can be defined as any null pointer constant. Thus existing code can retain definitions of NULL as 0 or 0L, but an implementation may also choose to define it as (void*)0. This latter form of definition is convenient on architectures where sizeof(void*) does not equal the size of any integer type. It has never been wise to use NULL in place of an arbitrary pointer as a function argument, however, since pointers to different types need not be the same size. The library avoids this problem by providing special macros for the arguments to signal, the one library function that might see a null function pointer.

大意就是: NULL 可以定义为任何空指针常量。因此,现有的代码可以保留 NULL 的定义为 00L (32位和64位的区别),或者直接就是由 0 或者 0L 转成的成 void*

接下来我们来看下 C++ 14(N4296)中所定义的 null pointer

A null pointer constant is an integer literal (2.13.2) with value zero or a prvalue of type std::nullptr_t.

A null pointer constant can be converted to a pointer type; the result is the null pointer value of that type and is distinguishable from every other value of object pointer or function pointer type. Such a conversion is called a null pointer conversion. Two null pointer values of the same type shall compare equal. The conversion of a null pointer constant to a pointer to cv-qualified type is a single conversion, and not the sequence of a pointer conversion followed by a qualification conversion (4.4). A null pointer constant of integral type can be converted to a prvalue of type std::nullptr_t. [ Note: The resulting prvalue is not a null pointer value. —end note ]

第一句话大意是 空指针常量是一个值为 0 的整型字面值或一个类型为 std::nullptr_tprvalue

2. C 中的 NULL

C 语言中,NULL 通常被定义为: #define NULL ((void *)0)

所以说 NULL 实际上是一个空指针,如果在 C 语言中写入以下代码,编译是没有问题的,因为在 C语言中把空指针赋给 intchar 指针的时候,发生了隐式类型转换,把 void 指针转换成了相应类型的指针。

int  *pi = NULL;
char *pc = NULL;

3. C++ 中的 NULL

以上代码如果使用 C++ 编译器来编译则是会出错的,因为 C++ 是强类型语言,void* 是不能隐式转换成其他类型的指针的,所以实际上编译器提供的头文件做了相应的处理:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

C++ 中,NULL 实际上是 0

因为 C++ 中不能把 void* 类型的指针隐式转换成其他类型的指针,所以为了空指针的表示问题,C++引入了 0 来表示空指针,这样就有了上述代码中的 NULL 宏定义。

但是实际上,用 NULL 代替 0 表示空指针在函数重载时会出现问题,程序执行的结果会与我们的想法不同,举例如下:

#include <iostream>
using namespace std;

void func(void* t)
{
    cout << "func1" << endl;
}

void func(int i)
{
    cout << "func2" << endl;
}

int main()
{
    func(NULL);  
    return 0;
}

运行后输出结果:

main.cpp: In function ‘int main()’:
main.cpp:16:14: error: call of overloaded ‘func(NULL)’ is ambiguous
     func(NULL);  

报错信息显示有歧义。

3. C++ 中的 nullptr

为解决 NULL 代指空指针存在的二义性问题,也就是上面遇到的报错问题,在C++11 版本中特意引入了 nullptr 这一新的关键字来代指空指针,如下所示

#include <iostream>
using namespace std;

void func(void* t)
{
    cout << "func1" << endl;
}

void func(int i)
{
    cout << "func2" << endl;
}

int main()
{
    func(nullptr);  // func1
    return 0;
}

可以看到程序可以正常输出与我们预期相同的结果。

4. 总结

NULLC++ 中就是 0,这是因为在 C++void* 类型是不允许隐式转换成其他类型的,所以之前 C++ 中用 0 来代表空指针,但是在重载整形的情况下,会出现上述的问题。

所以,C++11 加入了 nullptr ,可以保证在任何情况下都代表空指针,而不会出现上述的情况。

因此,建议使用 nullptr 替代 NULL ,而 NULL 就当做 0 使用。

参考:
https://blog.csdn.net/qq_18108083/article/details/84346655

标签:null,28,void,nullptr,C++,NULL,pointer,指针
来源: https://blog.csdn.net/wohu1104/article/details/116848286

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有