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語言中,以下定義都是合法的:it

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

    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*指針。di

    return 0;
}
    因爲C++支持函數重載,此時NULL的定義就會帶來歧義,當咱們調用overloaded(NULL);的時候,編譯器沒法確認,究竟是把NULL做爲常量0仍是做爲 (void *)0,所以編譯沒法經過。co

    爲了解決這個問題,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; }  

相關文章
相關標籤/搜索