C++ NULL和nullptr区别

C++11引入了nullptr以解决NULL作为空指针在C++中的二义性问题。NULL在C++中实际上是0,这在函数重载时可能导致错误的选择。 nullptr保证了在所有情况下都明确表示空指针,推荐使用nullptr替代NULL。

在编写C程序的时候只看到过NULL,而在C++的编程中,我们可以看到NULL和nullptr两种关键字,其实nullptr是C++11版本中新加入的,它的出现是为了解决NULL表示空指针在C++中具有二义性的问题,为了弄明白这个问题,我查找了一些资料,总结如下。

一、C程序中的NULL

在C语言中,NULL通常被定义为:#define NULL ((void *)0)

所以说NULL实际上是一个空指针,如果在C语言中写入以下代码,编译是没有问题的,因为在C语言中把空指针赋给int和char指针的时候,发生了隐式类型转换,把void指针转换成了相应类型的指针。

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

二、C++程序中的NULL

但是问题来了,以上代码如果使用C++编译器来编译则是会出错的,因为C++是强类型语言,void*是不能隐式转换成其他类型的指针的,所以实际上编译器提供的头文件做了相应的处理:

#ifdef __cplusplsus
#define NULL 0
#else
#define NULL ((void *)0)
#endif

可见,在C++中,NULL实际上是0.因为C++中不能把void*类型的指针隐式转换成其他类型的指针,所以为了结果空指针的表示问题,C++引入了0来表示空指针,这样就有了上述代码中的NULL宏定义。

但是实际上,用NULL代替0表示空指针在函数重载时会出现问题,程序执行的结果会与我们的想法不同,举例如下:

#include <iostream>
using namespace std;
void func(void* i)
{
   cout << "func1" << endl;
}
void func(int i)
{
   cout << "func2" << endl;
}

void main(int argc, char* argv[]){
   func(NULL);
   func(nullptr);
   getchar();
}  

  

在这段代码中,我们对函数func进行可重载,参数分别是void*类型和int类型,但是运行结果却与我们使用NULL的初衷是相违背的,因为我们本来是想用NULL来代替空指针,但是在将NULL输入到函数中时,它却选择了int形参这个函数版本,所以是有问题的,这就是用NULL代替空指针在C++程序中的二义性。

三、C++中的nullptr

为解决NULL代指空指针存在的二义性问题,在C++11版本(2011年发布)中特意引入了nullptr这一新的关键字来代指空指针,从上面的例子中我们可以看到,使用nullptr作为实参,确实选择了正确的以void*作为形参的函数版本。

总结:

NULL在C++中就是0,这是因为在C++中void* 类型是不允许隐式转换成其他类型的,所以之前C++中用0来代表空指针,但是在重载整形的情况下,会出现上述的问题。所以,C++11加入了nullptr,可以保证在任何情况下都代表空指针,而不会出现上述的情况,因此,建议以后还是都用nullptr替代NULL吧,而NULL就当做0使用。

其他:在没有C++ 11的nullptr的时候,我们怎么解决避免这个问题呢?

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

 

<think>好的,我现在需要回答用户关于C++NULLnullptr区别的问题。首先,我得回忆一下自己之前学过的相关知识,确保信息的准确性。 首先,我记得在C++中,NULL通常被定义为0或者((void*)0),这可能是从C语言继承过来的。而nullptrC++11引入的新关键字,专门用来表示指针。那这两个的区别主要在于类型重载函数处理上吧? 接下来,我应该详细分析它们的差异。类型方面,NULL作为宏定义,如果编译器将其视为整数0,那么在需要指针类型的上下文中可能会导致类型不匹配的问题。而nullptr的类型是std::nullptr_t,可以隐式转换为任何指针类型,这样在类型安全上更好。 然后想到重载函数的例子,比如有一个函数重载接受int指针参数。当传入NULL时,可能会调用接受int的版本,而传入nullptr则会正确调用指针版本,这应该是关键区别之一。用户可能需要这样的例子来理解应用场景。 另外,模板推导也是一个点。当使用NULL时,模板参数可能被推导为int,而nullptr会正确推导为指针类型,这会影响模板函数的实例化,可能导致错误或预期行为。 还需要注意兼容性,C++11之后推荐使用nullptr,而NULL在旧代码中常见。同时,在C语言中,nullptr不存在,所以跨语言项目需要注意这一点。 然后要组织这些点,用清晰的结构表达出来。可能分成几个部分:定义与历史背景、类型差异、重载函数影响、模板推导、代码示例、总结建议。这样用户能逐步理解。 需要确保例子正确,比如写一个函数重载的例子,展示NULLnullptr的不同行为。同时,在模板例子中,使用decltype或者类型推导的结果来展示两者的差异。 还要注意术语的准确性,比如NULL是宏,而nullptr是关键字,类型是std::nullptr_t,这些都要正确无误地表达。 最后总结时,强调nullptr在类型安全现代C++中的优势,建议在新项目中使用nullptr替代NULL,同时注意兼容性情况。 可能还需要检查是否有其他区别,比如在异常抛出或类型转换时的表现,但暂时想到的主要是类型重载相关的问题。确保覆盖用户可能关心的主要方面,不遗漏重要点。</think>C++中`NULL``nullptr`的区别可以从以下方面逐步理解: --- ### 一、定义与历史背景 1. **`NULL`** - 传统C/C++宏定义,通常被实现为整数`0`或指针形式的`((void*)0)` - 例如:`#define NULL 0` 或 `#define NULL ((void*)0)` - 因历史原因,**在指针整型间存在二义性** 2. **`nullptr`** - C++11引入的关键字,**明确表示指针常量** - 类型为`std::nullptr_t`,可隐式转换为任意指针类型 --- ### 二、类型差异(关键区别) - **`NULL`的类型** ```cpp int* p = NULL; // 可能被推导为 int* p = 0; void func(int); // 可能意外匹配整型重载版本 ``` - **`nullptr`的类型** ```cpp int* p = nullptr; // 明确指针,类型为 std::nullptr_t void func(int*); // 精确匹配指针重载版本 ``` --- ### 三、重载函数的歧义问题 **示例代码**: ```cpp void func(int) { cout << "int版本" << endl; } void func(char*) { cout << "指针版本" << endl; } func(NULL); // 输出 "int版本"(若NULL=0) func(nullptr); // 输出 "指针版本" ``` - **`NULL`可能错误匹配整型重载** - **`nullptr`始终匹配指针重载** --- ### 四、模板推导差异 **示例代码**: ```cpp template<typename T> void check_type(T t) {} check_type(NULL); // T被推导为 int(若NULL=0) check_type(nullptr); // T被推导为 std::nullptr_t ``` - **`NULL`可能导致模板参数推导错误** - **`nullptr`保留指针类型信息** --- ### 五、代码安全性与现代C++实践 1. **避免隐式类型转换** ```cpp char* ch = NULL; // 可能编译警告(整型转指针) char* ch = nullptr; // 安全,无警告 ``` 2. **与`auto`配合更清晰** ```cpp auto p1 = NULL; // p1类型为 int(若NULL=0) auto p2 = nullptr; // p2类型为 std::nullptr_t ``` --- ### 六、总结与建议 | 特性 | `NULL` | `nullptr` | |--------------|-------------------------|-------------------------| | **类型** | 整型或`void*` | `std::nullptr_t` | | **重载匹配** | 可能误匹配整型 | 精确匹配指针 | | **模板推导** | 可能推导为整型 | 保留指针类型信息 | | **C++版本** | C++03及之前 | C++11起 | **建议**: - 在新代码中**始终使用`nullptr`** - 旧代码迁移时逐步替换`NULL` - 需注意:C语言不支持`nullptr`(C++特有)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值