106.nullptr和NULL

发布时间 2023-07-15 12:35:07作者: CodeMagicianT

106.nullptr和NULL

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博客]