C++11新特性之nullptr

article/2025/8/28 4:50:36

        在C++11之前的C++98/03我们使用空都是NULL关键字,后来C++11之后新增了nullptr关键字来表示空。那么有了NULL还要弄个nullptr出来干什么呢?是不是吃太饱了?

        为了来剖析这两者的区别,我们先来看一个什么是野指针;

int serven_1 = 9;
int* serven_p;
int* serven_q = &serven_1;

        上面的代码中,serven_p就是野指针,因为定义他的时候没有给他指向的地方,导致他指向了哪些不可用的内存区域:

        所以你定义了指针,就算没有使用他,你也要给个空给他,不然等到内存溢出崩溃的时候,不仅他会哭,你也会被急哭。

        在C++98/03标准中,我们在定义一个指针并且给其赋值为空的时候有两种写法,不仅可以使用NULL,也可以使用0,不信你去试试看:

int* serven_p = NULL;
int* serven_q = 0;

        这两种写法完全木有问题,都是OK的。但还是推荐使用第一种写法。毕竟代码编写要规范嘛(这里备注一下:代码编写不规范真的会被打,从现在开始就要养成良好的编程习惯)。

        上面的指针serven_q直接附了0是什么意思呢?有没有联想到大学老师给你上课的时候,反复敲着黑板跟你们说:“咳咳咳~,大家注意了,指针指向的是变量的地址,他本身也是个内存空间,只是这个内存空间存放的是他指向的变量在内存中的地址”。所以呢,这里的serven_q相当于指向了0地址,也就是0x0000 0000这个内存空间。这个0地址呢,在很多操作系统(像Windows、Linux的等等)是不允许用户操作使用的,例如:

#include <QCoreApplication>
#include <iostream>
using namespace std;int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int* serven_p = 0;// *serven_p = 4;          // 这是不允许的printf("%p\n", serven_p);// printf("%d\n", *serven_p);return a.exec();
}

运行结果:

结果分析:

    serven_p指向的是0地址。

        在上面的代码给鲁豫看的话,她会说:我不信不信就不信啰,直接证明给你看,把代码中的两句注释语句恢复:

#include <QCoreApplication>
#include <iostream>
using namespace std;int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int* serven_p = 0;*serven_p = 4;printf("%p\n", serven_p);printf("%d\n", *serven_p);return a.exec();
}

运行结果:

结果分析:

        看到了吧,打印出来后啥都没有。这下可以相信了吧。

        但是在日常编程中,我们还是习惯使用NULL来给指针做初始化,但是NULL并不是C++的关键字,它是一个宏定义。在Visual Studio平台中,当你在编写代码中转至NULL的定义的时候,会跳到afx.h显示下面的代码:

...
#define NULL    0
...

  其实NULL宏定义就是一个0,惊不惊讶!反正我是挺惊讶的。好吧,既然它是0,那么就当它是空吧,这个披着外皮的狼,居然骗了我们这么多年。那就用它吧。

        等会,小编突然想到一个Bug,当NULL作为函数参数的时候会有歧义,例如:​​​​​​​

#include <QCoreApplication>
#include <iostream>
using namespace std;void Func_serven(void* serven_void){cout<<"I am void fucntion!"<<endl;
}void Func_serven(int serven_zero){cout<<"I am zero fucntion!"<<endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Func_serven(NULL);Func_serven(0);return a.exec();
}

运行结果:

结果分析:

        对于参数0来讲,它确实是个0,那么调用函数Func_serven(int serven_zero)名正言顺。而对于参数NULL来讲,我们是要它传给第一个函数的才对,但是跟我们想的完全不一样。

        那么怎么样做才能达到我们的预期效果呢?很简单,在NULL参数的前面加上强制类型转换就可以了,将其转换成void*:​​​​​​​

#include <QCoreApplication>
#include <iostream>
using namespace std;void Func_serven(void* serven_void){cout<<"I am void fucntion!"<<endl;
}void Func_serven(int serven_zero){cout<<"I am zero fucntion!"<<endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Func_serven((void*) NULL);        // 强制类型转换Func_serven(0);return a.exec();
}

运行结果:

这样就OK啦!

        所以通过上面的例子,还是觉得使用NULL不太妥当。所以呢C++11标准委员会也考虑到这一点,但是他们又不想抛弃NULL这个宏定义,因为程序员已经对NULL很亲切了,突然之间抛弃它会很舍不得。所以呢在C++11新特性中引入了一个新的关键字nullptr。

        nullptr是nullptr_t类型的右值常量,专门用于初始化空类型的指针。而nullptr_t是在C++11新增加的数据类型,跟int类型的功能一样,只是int是整型类型,而nullptr_t是指针空值类型。也就是说呢,nullptr仅仅是该类型的一个实例对象(也就是已经定义好的,可以直接使用)。当然了,我们也可以定义出多个和nullptr完全一样的实例对象,例如:

nullptr_t ser_ptr;
int* serven_1 = ser_str;      // 定义一个整型指针,指向空

        nullptr可以被隐式转换成任意的指针类型:

int* serven_3 = nullptr;
char* serven_4 = nullptr;
double* serven_5 = nullptr;

        不同类型的指针变量都可以使用nullptr类初始化,编译器会将nullptr隐式转换成int*、char*、double*指针类型。

        此外,nullptr也可以解决上面NULL的数参数调用的问题:

#include <QCoreApplication>
#include <iostream>
using namespace std;void Func_serven(void* serven_void){cout<<"I am void fucntion!"<<endl;
}void Func_serven(int serven_zero){cout<<"I am zero fucntion!"<<endl;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Func_serven(nullptr);nullptr_t ser_ptr;               // 你可以定义属于自己的空对象Func_serven(ser_ptr);Func_serven(0);return a.exec();
}

运行结果:

结果分析:

        因为nullptr无法隐式转换为整型,而可以隐式匹配指针类型,因此运行结果和我们预期的一样。另外,可以定义自己的空对象。

        但是使用nullptr_t一定要在支持C++11的编译平台上才可以使用。像Visual Studio平台都要2010版本之后才能使用。G++编译器至少要4.6.1才能使用。

总结:一般使用nullptr来编程会使我们的程序更加健壮。


http://chatgpt.dhexx.cn/article/I1ul5NMb.shtml

相关文章

C语言nullptr错误,c/c++中的NULL,nullptr,0

NULL,nullptr与0 0 NULL C语言中 C++中 隐式类型转换 nullptr 预处理中的条件编译语句 0 在我们的程序中,单纯一个0,在不同的类型中有着不同的意思 0,是一个空字符常量,他在ASCII中的序号就是0,是一个字符串的结束标准 ‘0’,表示一个字符0,他在ASCII中的序号是48 “0”…

C语言nullptr错误,C ++中的nullptr到底是什么

对于有经验的C ++和那些了解现代C ++编程语言的人来说,C ++中的nullptr到底是什么,这将是非常简单的问题。但是nullptr不仅是C ++中的编程语言,而且为了解释这一点,我们先了解一下NULL的问题,然后我们将深入研究nullptr的简单实现以及nullptr的一些用例。为什么我们需要nu…

C++中NULL和nullptr的区别

在编写C程序的时候只看到过NULL&#xff0c;而在C的编程中&#xff0c;我们可以看到NULL和nullptr两种关键字&#xff0c;其实nullptr是C11版本中新加入的&#xff0c;它的出现是为了解决NULL表示空指针在C中具有二义性的问题&#xff0c;为了弄明白这个问题&#xff0c;我查找…

C++11中的nullptr

一、什么是nullptr&#xff1f; nullptr是c11的空指针&#xff0c;可以理解为 NULL的升级版。 二、解决什么问题&#xff1f; 首先&#xff0c;在C语言中&#xff0c;NULL是被定义成这样的#define NULL ((void *)0)。 而C中&#xff0c;NULL是被定义成这样#define NULL 0。 …

C++基础:指针空值(nullptr)

初始化指针是将其指向一个“空”位置&#xff0c;比如0。由于大多数计算机系统不允许用户程序写地址为0的内存空间&#xff0c;倘若程序无意中对该指针所指地址赋值&#xff0c;通常在运行时就会导致程序退出。虽然程序退出并非什么好事&#xff0c;但这样一来错误也容易被程序…

【Kafka】消息的同步发送和异步发送

文章目录 概述1. sync vs async1.1 java代码同步和异步 2. 可靠性机制(ack属性配置)2.1 oneway 3. 一般配置4. 同步异步和ack的联系和区别参考 概述 kafka有同步&#xff08;sync&#xff09;、异步&#xff08;async&#xff09;以及oneway这三种发送方式&#xff0c;某些概念…

http请求与响应,同步异步请求以及异步请求axios的配置

文章目录 httphttp简介&#xff0c;协议http请求http响应接收请求行请求头数据 同步异步请求异步请求axios的配置配置文件 http http简介&#xff0c;协议 http是超文本传输协议 &#xff08;HyperText Transfer Protocol&#xff09;服务器传输超文本 到本地浏览器的传送协议…

ajax同步和异步的区别

一、同步访问和异步访问的区别&#xff0c;先从概念上区别&#xff1a; 1、同步的概念应该是来自于操作系统中关于同步的概念。 2、不同进程为协同完成某项工作而在先后次序上调整(通过阻塞,唤醒等方式)。同步强调的是顺序性&#xff0c;谁先谁后&#xff1b;异步则不存在这种顺…

C++ LinuxWebServer项目(5)同步异步日志系统

一、前言 对于任何一个服务器而言,日志系统的设计是非常重要的,尝试设计一个简易的同步异步日志系统来完成系统日志的记录。 二、基础知识 日志,由服务器自动创建,并记录运行状态,错误信息,访问数据的文件。 同步日志,日志写入函数与工作线程串行执行,由于涉及到I…

一文搞懂同步异步阻塞非阻塞

相信很多人在面试的过程中&#xff0c;都被问到过同步和异步的区别、阻塞和非阻塞的区别&#xff0c;以及这两对关系又有什么联系&#xff1f;本文尽可能从专业的角度&#xff0c;用易懂的语言&#xff0c;帮助大家理解 01 前置知识 用户空间和内核空间 操作系统可以支持多个…

同步异步半同步分离式通信

同步通信&#xff1a;采用统一的时钟信号 读数据 T1上升沿主设备给出从设备地址 T2上升沿给出读命令 T3上升沿读数据 T4上升沿撤销 写数据 T1上升沿主设备给出从设备地址 T1下降沿给出数据 T2上升沿给写命令 T4上升沿撤销 异步通信分为三类&#xff1a; 不互锁&#…

一篇文章理解 同步异步、阻塞非阻塞

前述 同步异步&#xff0c;阻塞非阻塞是一些非常常见的概念&#xff0c;但是对于开发者来说往往是用到了很难说清楚。 笔者专门整理了下这方面的概念&#xff0c;作此文以记之。 这部分内容可能存在一些争议&#xff0c;如有不同意见欢迎评论交流。 概念 个人理解同步异步与阻…

ES6同步异步处理

同步和异步 1.同步就是代码从上而下依次执行&#xff0c;除了函数或则回调函数 2.异步也有先后之分但是不明显&#xff0c;等js代码先执行同步后再去执行异步的代码. 如何处理同步异步的问题&#xff08;ES6的Promise&#xff09; 接上面&#xff0c;看下面的代码 var arr[…

前端学习-同步异步问题

在做实作课作品时&#xff0c;出现过对象中变量访问不到的情况&#xff0c;查阅相关资料发现时同步异步的问题&#xff0c;这篇文章帮助我理清思路&#xff0c;希望也能帮助你们更好地理解同步异步。 一、什么是同步/异步任务&#xff1f; 同步任务&#xff1a;指的是在主线程…

dubbo同步异步调用

通常我们通过dubbo调用服务接口&#xff0c;等待提供方处理完响应结果&#xff0c;这是同步调用&#xff1b;也是默认的调用方式。通过查看原吗DubboInvoker可以看到&#xff1a; 整体来说有三种方式&#xff1a; 1、是否关注结果&#xff0c;returntrue关注&#xff0c;默认也…

理解:什么是同步和异步?什么是阻塞和非阻塞?

一、同步和异步 同步与异步是指访问数据的机制&#xff0c;同步一般指主动请求并等待IO操作完成的方式。 异步则指主动请求数据后便可以继续处理其它任务&#xff0c;随后等待IO操作完毕的通知。 同步和异步最大的区别就在于&#xff1a;同步需要等待&#xff0c;异步不需要等…

CPUGPU加速计算

1、CPU(Centrol Processing Unit) CPU上的大部分面积做了cache 和控制逻辑&#xff0c;天然适合做复杂串行程序&#xff1b; 2、GPU(Graphic Processing Unit): GPU有更多的晶体管用于数据处理&#xff0c;特别适用于解决并行计算的问题。可以使程序执行速度加快。为处理图形…

tensorflow使用GPU加速

测试faster-rcnn时&#xff0c;cpu计算速度较慢&#xff0c;调整代码改为gpu加速运算 将 with tf.Session() as sess: 替换为 1 gpu_options tf.GPUOptions(per_process_gpu_memory_fraction0.9) 2 with tf.Session(configtf.ConfigProto(gpu_optionsgpu_options,log_device_…

GPU 及其加速库简介

文章目录 一、GPU 与 CPU 简介1、GPU 与 CPU 的区别2、GPU 分类3、GPU&#xff08;NVIDIA A100 &#xff09; 介绍 二、CUDA 简介1、多版本 CUDA 切换2、为各种 NVIDIA 架构匹配 CUDA arch 和 gencode 三、OpenCL 简介1、OpenCL 平台模型2、OpenCL 执行模型 四、参考资料 一、G…

Pytorch使用GPU加速的步骤

CUDA&#xff08;Compute Unified Device Architecture&#xff09;&#xff0c;是显卡厂商NVIDIA推出的运算平台。 CUDA是一种由NVIDIA推出的通用并行计算架构&#xff0c;该架构使GPU能够解决复杂的计算问题。近些年来&#xff0c;显卡的计算能力越来越强大&#xff0c;如果只…