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

本文解析了C++中NULL和nullptr的区别,NULL在C++中等同于0,用于void*类型,可能导致函数重载冲突;而nullptr是C++11引入的专用关键字,避免了类型歧义,推荐在现代C++编程中使用nullptr。
摘要由CSDN通过智能技术生成

最近看公司代码的时候发现在判断指针是否为空的时候,有的时候用的是 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wohu007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值