首页 > 编程语言 >3.C++中NULL和nullptr区别

3.C++中NULL和nullptr区别

时间:2023-08-02 22:11:07浏览次数:39  
标签:int void nullptr C++ cpp NULL

3.C++中NULL和nullptr区别

1.NULL是什么

《NULL,0,'\0',"0","\0"的区别》一文中,我们已经知道了在C中NULL是什么,在C的头文件中,通常定义如下:

#define NULL ((void*)0)

但是在C++中,它是这样定义的:

#define NULL 0

可以在stddef.h看到完整的这段:

#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

也就是说,在C++中,NULL不过也是0罢了,把它当成空指针只是一个无可奈何的选择罢了。

那么为什么在C++和C中不一样呢?因为C++中不能将void *类型的指针隐式转换成其他指针类型,从下面的例子可以看出来:

//null.cpp
#include<iostream>
int main(void)
{
    char p[] = "12345";
    int *a = (void*)p;
    return 0;
}

编译:

$ g+ -o null null.cpp
null.cpp: In function 'int main()':
null.cpp:5:17: error: invalid conversion from 'void*' to 'int*' [-fpermissive]
int *a =(void*)p;

所以不能将NULL定义为(void*)0。

2.nullptr

nullptr并非整型类别,甚至也不是指针类型,但是能转换成任意指针类型。nullptr的实际类型是std:nullptr_t。

2.1为什么该使用nullptr

回到最开始的问题,为什么作为指针的语义,我们应该使用nullptr,而不是NULL。 请看下面的代码:

#include<iostream>
using namespace std;

void test(void *p)
{
    cout<<"p is pointer "<<p<<endl;
}

void test(int num)
{
    cout<<"num is int "<<num<<endl;
}

int main(void)
{
    test(NULL);
    return 0;
}

编译:

$ g++ -o test test.cpp
main.cpp: In function ‘int main()’:
main.cpp:16:14: error: call of overloaded ‘test(NULL)’ is ambiguous
test(NULL);

很不幸,编译报错了,提示我们有二义性,两个都可以匹配,因此最终报错。

但是如果我们使用nullptr却不会:

test(nullptr);

除了这点之外,在C++模板中它还有更好的表现。 看下面的代码:

#include<iostream>
using namespace std;

template<typename Type1,typename ptrType>
void test(Type1 fun, ptrType ptr)
{
    /*do something*/
    fun(ptr);
    return;
}

void fun(int *val)
{
    cout<<"fun"<<endl;
}

int main(void)
{
    test(fun, NULL);
    return 0;
}

编译报错了:

main.cpp:8:8: error: invalid conversion from ‘long int’ to ‘int*’ [-fpermissive]
fun(ptr);

很显然NULL被推导为long int,而不是空指针,因而导致函数类型不匹配而报错。

但是如果我们用nullptr就不会有上面的问题。

注:nullptr在C++ 11中才出现。

参考:[(9条消息) nullptr与NULL的区别_nullptr和null区别_qq_37032670的博客-CSDN博客]

标签:int,void,nullptr,C++,cpp,NULL
From: https://www.cnblogs.com/codemagiciant/p/17601908.html

相关文章

  • 2.简要说明C++的内存分区
    2.简要说明C++的内存分区1.一个由C/C++编译的程序占用的内存分为以下几个部分:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈......
  • 4.可以说一下你了解的C++得内存管理吗?
    4.可以说一下你了解的C++得内存管理吗?1.一个由c/C++编译的程序占用的内存分为以下几个部分:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自......
  • 5.C++中类的数据成员和成员函数内存分布情况
    5.C++中类的数据成员和成员函数内存分布情况非静态成员的数据类型大小之和。编译器加入的额外成员变量(如指向虚函数表的指针)。为了边缘对齐优化加入的padding。空类(无非静态数据成员)的对象的size为1,当作为基类时,size为0。C++类是由结构体发展得来的,所以他们的成员变......
  • 128.用C语言实现C++的继承
    128.用C语言实现C++的继承#include<iostream>usingnamespacestd;//C++中的继承与多态structA{virtualvoidfun()//C++中的多态:通过虚函数实现{cout<<"A:fun()"<<endl;}inta;};structB:publicA//C++中的继承:B类公有继......
  • c++控制台时钟显示时间
    在旧电脑上刷了ubuntu的服务器版本,开着的时候旧电脑(yoga)的屏幕就处于了无用的状态。为了更好的利用这个屏幕,简单使用c++写了一个显示时间的代码。由于这台yoga的屏幕是可以360翻转的,所以给时间的显示也增加了一点翻转功能。1#include<iostream>2#include<ctime>3#......
  • 恶意代码分析实战 lab 20-1 20-2 20-3 C++恶意代码分析,难度提升
    本次实验我们将会分析lab20-1,lab20-2文件。先来看看要求解答的问题Lab20-1需要回答的问题如下Q1.在0x401040处的函数采用了什么参数?Q2.哪个URL被用来调用URLDownloadToFile?Q3.这个程序做了什么事情?在实验任务一当中我们来分析lab20-1首先载入IDA第一个call是在401008,是一个......
  • 软件测试|SQL中的null值,该如何理解?
    深入理解SQL中的Null值:处理缺失数据的重要概念简介Null值在SQL中是用于表示缺失或未知数据的特殊值。本文将深入探讨Null值的概念、处理方法和注意事项,以帮助读者更好地理解和处理SQL中的缺失数据。在SQL数据库中,Null值是一种特殊的值,用于表示缺失或未知的数据。它与其他具体的数值......
  • C++逆向分析——友元、内部类、命名空间和static
    友元友元可以理解为:朋友、元素;老师认为这个友元是C++中的一个垃圾,因为友元的存在破坏了面向对象的封装性,不推荐使用,之所以有这个章节是因为有人不了解这个概念。注意:在一些新版本的C++编译器里面已经不再提供类似于友元这样的特性了。大家都知道在C++中对象的私有成员,外部是无法访......
  • C++逆向分析——对象拷贝
    对象拷贝我们通常存储对象,都用数组、列表之类的来存储,那如下所示我们使用数组来存储对象,但是在工作中发现这个数组不够用了,就需要一个更大的数据,但我们重新创建一个数组还需要把原来的数据复制过来;在C语言中可以使用函数来进行拷贝,直接拷贝内存,在C++中实际上跟C语言要做的事情是一......
  • C++逆向分析——模版
    模版假设有一个冒泡排序的函数:voidSort(int*arr,intnLength){inti,k;for(i=0;i<nLength;i++){for(k=0;k<nLength-1-i;k++){if(arr[k]>arr[k+1]){inttemp=arr[k];arr[k]=arr[k+1];arr[k+1]=temp;}}}}但是这个冒......