C++11 NULL和nullptr

博客主要探讨了C++11引入nullptr的原因。在C语言中,NULL可用于多种类型定义;而在C++里,因支持函数重载,NULL的定义会带来歧义。C++11引入的nullptr常量是std::nullptr_t类型,能解决整型和指针类型的重载问题,但对不同指针类型的重载函数仍有局限,可通过std::nullptr_t类型解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    众所周知,C语言使用NULL常量来表示空指针,为什么C++11还要增加新的nullptr来表示空指针呢?

    1,我们首先查看NULL的定义:

#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL             /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else   /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else   /* C++ */
#define NULL 0
#endif  /* C++ */
#endif  /* G++ */
#endif  /* NULL not defined and <stddef.h> or need NULL.  */
#undef  __need_NULL
    从上面的定义可以看出,如果定义了__GNUG__,编译器NULL其实就是__null,__null是编译器相关的行为(要么是常量0,要么是 (void *)0),有待进一步研究确认。

    因此,在C语言中,如下定义都是合法的:

    int a = NULL;
    char b = NULL;
    int *ptr = NULL;
 

    2,在C++中,考虑如下重载示例:

void overloaded(int value) {
    std::cout << "int value" << std::endl;
}


void overloaded(int *ptr) {
    std::cout << "int *ptr" << std::endl;
}


int main() {
    overloaded(NULL);        // 歧义,因为NULL既可以是常量0,也可以是 void*指针。

    return 0;
}
    由于C++支持函数重载,此时NULL的定义就会带来歧义,当我们调用overloaded(NULL);的时候,编译器无法确认,到底是把NULL作为常量0还是作为 (void *)0,因此编译无法通过。

    为了解决这个问题,C++11引入了nullptr常量,该常量是std::nullptr_t类型。std::nullptr_t类型可以转换为任意指针类型(类似于void *,也可以转换为任意指针类型),同时也可以转换为bool类型(用以支持条件判断 !ptr),但是不能转换成整型类型。这样便消除了上面的重载歧义。

    overloaded(nullptr);   // ok,调用void overloaded(int *ptr);版本

    转换成bool类型示例如下:

int main() {
    std::nullptr_t ptr = nullptr;

    if (!ptr) {    // std::nullptr_t类型转换成bool类型
        std::cout << "nullptr" << std::endl;
    }

    return 0;
}
 

    3,当然,nullptr只是解决了整型和指针类型的重载问题,对于两个不同指针类型的重载函数,nullptr无法区分出来:

    

void overloaded(int *ptr) {
    std::cout << "int *ptr" << std::endl;
}


void overloaded(char *ptr) {
    std::cout << "char *ptr" << std::endl;
}


int main() {
    overloaded(nullptr);    // 歧义,依然无法区分 int *和 char *

    return 0;
}
    这时候,可以使用std::nullptr_t类型,如下:

void overloaded(int *ptr) {
    std::cout << "int *ptr" << std::endl;
}


void overloaded(char *ptr) {
    std::cout << "char *ptr" << std::endl;
}

void overloaded(std::nullptr_t ptr) {
    std::cout << "std::nullptr_t ptr" << std::endl;
}

int main() {
    overloaded(nullptr);    // ok,输出 std::nullptr_t ptr

    return 0;
}
 

    

    

转载于:https://my.oschina.net/yepanl/blog/1933927

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值