首页 > 编程语言 >C++中的NULL和nullptr

C++中的NULL和nullptr

时间:2024-11-26 23:13:35浏览次数:3  
标签:nullptr 整数 C++ 类型 NULL 指针

NULL 和 nullptr 都是用于表示空指针的常量,但它们在 C++ 中有一些重要的区别,特别是随着 C++11 引入了 nullptr 之后,nullptr 成为了更推荐的选择。以下是两者的主要区别:


1. 类型

  • NULL:在 C 和 C++ 中,NULL 是一个宏,通常定义为 0(或 (void*)0),它本质上是整数常量。由于它是一个整数常量,编译器在使用时可能无法区分空指针和零值的整数,因此可能会引起一些类型转换的问题。

    #define NULL 0
    
    • NULL 可以隐式转换为任何指针类型(因为 0 可以被视为空指针)。
    • 由于其是整数常量,有时可能会导致不明确的转换。
  • nullptrnullptr 是 C++11 中引入的一个关键字,专门用于表示空指针。它是一个类型安全的指针常量,具有明确的指针类型 (std::nullptr_t),并且不能隐式转换为整数类型。

    nullptr_t
    
    • nullptr 具有明确的类型 std::nullptr_t,并且只能用于指针类型。
    • 编译器能够识别 nullptr 并明确区分它与其他类型(如整数或枚举)。

2. 类型安全

  • NULL:由于 NULL 是一个宏,它通常等于 0,并且 0 是一个整数常量,所以 NULL 可以隐式转换为整数类型(这可能导致不明确的类型转换)。

    int* p = NULL;  // 可以通过隐式转换
    int i = NULL;   // 允许将空指针赋值给整数
    
  • nullptrnullptr 是类型安全的,它只能与指针类型匹配,并且不会进行隐式转换。这消除了由于将 NULL 用于整数类型而引起的潜在问题。

    int* p = nullptr;  // 正确
    int i = nullptr;   // 错误:不能将 nullptr 赋值给整数类型
    

    这样,nullptr 提供了更强的类型检查和防止误用。


3. 用于函数重载

由于 nullptr 具有明确的类型(std::nullptr_t),它可以帮助解决函数重载时的歧义问题,而 NULL 由于被定义为 0,可能导致不同类型重载之间的冲突。

例如,如果你有两个重载函数,一个接受指针,另一个接受整数类型,使用 NULL 可能会导致二义性:

void func(int) {
    std::cout << "Integer version\n";
}

void func(char*) {
    std::cout << "Pointer version\n";
}

int main() {
    func(NULL);  // 可能引起二义性:NULL 被视为 0,既可以是 int 类型也可以是指针类型
}

使用 nullptr 可以消除这种二义性,因为它明确表示为空指针:

int main() {
    func(nullptr);  // 明确调用指针版本
}

4. 容易出错的情况

  • NULL:如果在某些情况下将 NULL 用作整数或其他类型时,可能会导致逻辑错误或难以发现的 bug。

    if (some_pointer == NULL) {  // 检查空指针时没有问题
        // do something
    }
    
    if (some_pointer == 0) {    // 0 和 NULL 相同,但 0 可能被错误地用作整数
        // do something
    }
    
  • nullptrnullptr 不能与整数或其他类型隐式转换,因此不容易出错。

    if (some_pointer == nullptr) {  // 更安全,更明确
        // do something
    }
    

总结

特性NULLnullptr
类型 宏,通常等于 0(整数常量) 关键字,类型为 std::nullptr_t
类型安全 不安全,可能会隐式转换为整数类型 类型安全,不能隐式转换
使用范围 可用于指针和整数类型 仅用于指针类型
函数重载 可能导致重载歧义 消除重载歧义
C++标准 在 C 和 C++ 中都可以使用 从 C++11 引入

推荐使用 nullptr

  • 在 C++ 中,推荐使用 nullptr 代替 NULL,因为它更类型安全,避免了由于隐式转换引起的潜在问题,并且更清晰地表达了代码意图。

标签:nullptr,整数,C++,类型,NULL,指针
From: https://www.cnblogs.com/chentiao/p/18571155

相关文章

  • C++中单例模式和static的对比
    在编程中,单实例(Singleton)模式和使用 static 变量或方法 都能实现某些程度上的共享状态或限制实例数量,但它们的设计目的、适用场景以及实现方式存在本质区别。1.单实例(Singleton)模式特点:目标:确保一个类在全局范围内只有一个实例,并提供一个访问该实例的全局访问点。控制粒......
  • 【C++编程】五个分区: 堆、栈、静态(全区)区、 常量区 代码区
    在C++中,程序的内存管理被分为几个区域,这些区域每个都有其特定的用途。下面是你提到的五个分区的详细描述:一、栈区(Stack)用途:用于存储局部变量和函数调用时的上下文(如返回地址与参数等)。特点:采用先进后出(LIFO)原则进行管理。内存由编译器自动分配和释放,程序员无法手动干预。栈......
  • 自动驾驶之心全套面向自动驾驶的C++实战教程(视频 答疑)
    网课学习的好处有哪些课程地址https://pan.baidu.com/s/1GIsMJ9BGgjgbJCrsVNDi6A?pwd=2q491、学生学习自主性强:当学生在面对电脑时,会有一种自己未来掌握在自己手中的感觉,所有的操作完全由自己掌控,真正发挥学习的主观能动性。2、学生非限性学习:网络学习的学生不受年龄的限制,同......
  • 每日OJ_牛客_MT2棋子翻转_模拟_C++_Java
    目录牛客_MT2棋子翻转_模拟题目解析C++代码Java代码牛客_MT2棋子翻转_模拟棋子翻转_牛客题霸_牛客网描述:在4x4的棋盘上摆满了黑白棋子,黑白两色棋子的位置和数目随机,其中0代表白色,1代表黑色;左上角坐标为(1,1),右下角坐标为(4,4)。现在依次有一些翻转操作,要对以......
  • 告别内存泄漏!深入掌握C++11智能指针的强大魔法
    文章目录前言......
  • 什么是 C++ 中的多继承?它有哪些优缺点? 什么是虚继承?为什么要使用虚继承?
    1)什么是C++中的多继承?它有哪些优缺点?一、多继承的定义在C++中,多继承是指一个类可以从多个基类继承成员。例如:classBase1{public:voidfunc1(){//...}};classBase2{public:voidfunc2(){//...}};classDerived:......
  • C++ 1112 超标区间 (乙级)
    上图是用某科学研究中采集的数据绘制成的折线图,其中红色横线表示正常数据的阈值(在此图阈值是25)。你的任务就是把超出阈值的非正常数据所在的区间找出来。例如上图中横轴[3,5]区间中的3个数据点超标,横轴上点9(可以表示为区间[9,9])对应的数据点也超标。输入格式:输......
  • 【类的默认成员函数】构造函数&&析构函数【C++】
    【类的默认成员函数】构造函数&&析构函数【C++】任何一个类在我们不写的情况下,都会自动生成6个默认成员函数构造函数:初始化(不是开空间!)日常实操中最好自己写一个!!!!!!!!Date(){ _year=1; _month=1; _day=1;}特点(1)函数名和类名相同(2)无返回值(3)对象实例化时编译器自动调......
  • explicit关键字【C++】
    explicit关键字【C++】用来修饰只有一个参数的类构造函数,以表明该构造函数是显式的,而非隐式的禁止类对象之间的隐式转换,以及禁止隐式调用拷贝构造函数隐式类型转换inti=1;doubled=i;d被i赋值时【编译器会做】在中间产生一个临时变量再通过这个临时对象进行拷贝构......
  • C++练级计划->《多态》虚函数表,菱形继承多态
    目录什么是多态?多态的条件虚函数:虚函数的重写:协变 析构函数的重写C++11final和overridefinal:override:总结:三重对比:重载重写重定义对比抽象类多态的原理虚函数表为什么只能是父类的指针或者引用来调用才能形成多态? 动态绑定和静态绑定单继承的虚函数表 ......