zoukankan      html  css  js  c++  java
  • C++11 NULL和nullptr

     众所周知,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;
    }
    天上我才必有用,千金散尽还复来!
  • 相关阅读:
    iOS Graphics 编程
    如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1
    Python服务器开发二:Python网络基础
    Access一些问题
    托管调试助手报错
    ConnectionString
    百度也开源
    Microsoft SQL Server 错误代号: 15535 解决方法
    临时表的一个用法
    类型初始值设定项引发异常
  • 原文地址:https://www.cnblogs.com/lutaishi/p/13436257.html
Copyright © 2011-2022 走看看