【C++掌中宝】C++ 中的空指针救世主——nullptr

news/2024/9/25 13:09:59/

在这里插入图片描述

文章目录

  • 1. 什么是 NULL?
  • 2. NULL 在 C 和 C++ 中的区别
  • 3. C++11 引入 nullptr 的原因
  • 4. nullptr 与 NULL 的区别
  • 5. nullptr 的应用场景
  • 6. 模拟 nullptr 的实现
  • 7. 总结
  • 结语

1. 什么是 NULL?

在 C 和 C++ 编程中,NULL 常用于表示空指针,但它本质上是一个宏定义

  • 在C语言中,NULL 通常被定义为 (void *)0,也就是一个指向空的 void 指针。
  • 但在 C++ 中,NULL 常常被定义为整数常量 0

在传统的C头文件(stddef.h)中,可以看到如下代码:

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

由于在 C++ 中,void* 不能隐式转换为其他类型的指针,因此将 NULL 定义为 0。这导致在函数重载时可能会出现二义性问题

2. NULL 在 C 和 C++ 中的区别

在 C 语言中,NULL 定义为 (void *)0,它可以隐式转换为任何类型的指针。这使得以下代码在 C 中可以正常编译和运行:

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

然而,在 C++ 中,由于更严格的类型检查,void* 不能隐式转换为其他指针类型。因此,C++ 中的 NULL 通常被定义为整数常量 0。这导致了以下代码在 C++ 中的编译错误

int *pi = (void*)0;  // OK in C, error in C++

报错如下

在这里插入图片描述


除此之外,NULL 在函数重载时也会导致意外行为。例如,考虑以下代码:

#include<iostream>
using namespace std;
void f(int x)
{cout << "f(int x)" << endl;
}
void f(int* ptr)
{cout << "f(int* ptr)" << endl;
}
int main()
{f(0);f(NULL);
} // 这会调用哪个版本的 f()?

运行结果如下
在这里插入图片描述

由于 NULL 被定义为 0,这里会调用 int 参数的版本,而不是我们期望的指针版本,所以最后两个结果都是选择int 参数的版本。

3. C++11 引入 nullptr 的原因

为了消除 NULL 在 C++ 中的二义性问题,C++11 引入了 nullptr 作为一种新型空指针常量nullptr 是一个关键字,代表一种特殊类型,使用nullptr定义空指针可以避免类型转换的问题,因为它只能转换为任意指针类型,但不能转换为整数类型

例如,以下代码可以正确运行并调用我们期望的函数版本:

#include<iostream>
using namespace std;void f(int x) {cout << "foo(int x)" << endl;
}void f(int* ptr) {cout << "foo(int* ptr)" << endl;
}int main() {f(nullptr);  // 调用 f(int* ptr)return 0;
}

nullptr 的引入解决了函数重载中的二义性问题,确保空指针总是正确地匹配到指针类型的重载函数。

4. nullptr 与 NULL 的区别

虽然 NULL 仍然可以在 C++ 中使用,但它在特定场景下会引发错误或误解。相比之下,nullptr 是一种更加安全且明确的选择:

  • 在C++中NULL 通常是整数 0,会引发二义性问题。
  • nullptr 是一个指针常量,可以隐式转换为任意指针类型,不会引发二义性问题。

例如:

void func(int x) {cout << "func(int)" << endl;
}void func(char* p) {cout << "func(char*)" << endl;
}int main() {func(0);         // 调用 func(int)func(nullptr);   // 调用 func(char*)return 0;
}

5. nullptr 的应用场景

在 C++11 及更高版本中,推荐使用 nullptr 代替 NULL 来表示空指针,特别是在函数重载的场景下。例如:

int* p1 = nullptr;
if (p1 == nullptr) {cout << "p1 是空指针" << endl;
}

需要注意的是,nullptr 不能赋值给整数类型,因此以下代码会导致编译错误:

int n = nullptr;  // 编译错误

报错如下
在这里插入图片描述

6. 模拟 nullptr 的实现

对于不支持 C++11 的编译器,我们可以自己模拟实现 nullptr。以下是一个简单的实现:

const class nullptr_t {
public:template<class T>operator T*() const { return 0; }template<class C, class T>operator T C::*() const { return 0; }private:void operator&() const;
} nullptr = {};

7. 总结

NULL 是一个历史遗留的宏定义,虽然在 C++ 中仍然可以使用,但它会在特定场景下引发意外的行为和错误。为了消除这些问题,C++11 引入了 nullptr,作为一种类型安全的空指针表示。

在现代 C++ 编程中,强烈推荐使用 nullptr 代替 NULL,确保代码在空指针处理上更加明确和安全。

结语

通过本文,读者应当已经掌握了 nullptr 的基本概念、与 NULL 的区别以及如何在实际编程中应用它。如果你还在用 NULL,是时候拥抱 nullptr,让你的代码更加健壮吧!

今天的分享到这里就结束啦!如果觉得文章还不错的话,可以三连支持一下。

也可以点点关注,避免以后找不到我哦!

Crossoads主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的动力!
在这里插入图片描述


http://www.ppmy.cn/news/1530296.html

相关文章

keepalived+nginx实现高可用的案例详解(主从模式)

文章目录 keepalived什么是keepalivedkeeepalived的工作原理keepalived的特点 实现过程配置步骤&#xff1a;环境具体步骤ngx1ngx2效果测试 keepalived 什么是keepalived Keepalived 是一个高可用性&#xff08;High Availability, HA&#xff09;工具&#xff0c;主要用于 L…

传输大咖45 | 跨国传输大文件的高效、安全传输系统

企业的跨国合作以成为常态。在跨国合作过程中&#xff0c;大量数据需要在不同国家和地区之间传输。然而&#xff0c;在进行跨国大文件传输时&#xff0c;企业往往会遇到诸如速度慢、安全性低、数据合规性问题以及缺乏有效的日志审计和权限管理等一系列挑战。 跨国传输大文件面临…

UI自动化测试的边界怎么定义?

标题&#xff1a;定义UI自动化测试的边界&#xff1a;从0到1的详细指南 引言&#xff1a; UI自动化测试是现代软件开发过程中至关重要的一环。为了确保自动化测试的有效性和准确性&#xff0c;我们需要明确定义测试的边界。本文将从0到1为您提供一篇详细且规范的指南&#xf…

引用和指针的区别

引用&#xff08;reference&#xff09;和指针&#xff08;pointer&#xff09;都是 C 中用来间接访问内存中对象的机制&#xff0c;但它们有一些重要的区别。以下是它们在语法、用法和特性上的详细区别。 下面从7个方面来详细说明引用和指针的区别 1. 定义与语法区别 引用&…

C++ asio异步网络库学习记录

最近几天在学习asio异步网络库&#xff0c;今天整理下前几日学习asio库同步读写demo的案例&#xff0c;明天我会整理asio配置的过程。 之前也学习过winsocket&#xff0c;但是不论是winsock还是asio都经历这样几个阶段&#xff1a; 服务端&#xff1a; socket创建socket套接字…

STM32CubeIDE | 使用HAL库的ADC读取内部传感器温度

1、cubemx配置 1.1、系统配置 1.2、GPIO配置 PB2设置为“GPIO_Output” user label设置为“LED” 1.3、串口配置 模式选择为“Asynchronous”&#xff0c;其他默认 1.4、时钟树配置 全部保持默认 2、ADC配置 通道选择“Temperature Sensor Channel”&#xff0c;其他默认 …

14年408-计算机网络

第一题&#xff1a; 解析&#xff1a;OSI体系结构 OSI由下至上依次是&#xff1a;物理层-网络链路层-网络层-运输层-会话层-表示层-应用层。 因此直接为会话层提供服务的是运输层。答案选C 第二题&#xff1a; 解析&#xff1a;数据链路层-交换机的自学习和帧转发 主机a1向交换…

中电金信:源启智能视觉分析系统~助力各行业破局升级,释放新质生产力

作为人工智能与计算机视觉的交叉范畴&#xff0c;智能视觉模仿人类视觉机能&#xff0c;来对各种形式的视觉输入予以处理、理解以及决策。当下&#xff0c;智能视觉已然发展为应用广泛、市场覆盖面大且形式多元的产业方向&#xff0c;获得了国家政策的强力支持。数字化时代搭台…