C++11新機能-キーワードnullptrの導入

2547 ワード

1.nullptr導入の理由
nullptrを導入した理由はNULLから.CとC++プログラマーにとって、NULLに慣れていないに違いない.しかしCとC++のNULLは等価ではない.NULLはポインタがオブジェクトを指さないことを示すが、問題はNULLがキーワードではなくマクロ定義(macro)であることである.
1.1 NULLのCでの定義
Cでは、NULLはvoid*ポインタ値0として定義されます.
#define NULL (void*)0

ただし、NULLを整数0として定義することもできます.
1.2 NULLのC++での定義
C++では、NULLは整数0として明確に定義されています.
// lmcons.h   NULL     
#ifndef NULL  
#ifdef __cplusplus  
#define NULL    0  
#else  
#define NULL    ((void *)0)  
#endif  
#endif

1.3 C++がNULL上で不完全な互換性Cを選択した理由
根本的な原因はC++のリロード関数と関係がある.C++はマッチングパラメータのメカニズムを探索することによって最適マッチング(best-match)の関数を見つけようとするが,void*の暗黙型変換をサポートし続けると意味二義性(syntax ambiguous)の問題をもたらす.
//             
void foo(int i);  
void foo(char* p)  
  
foo(NULL); // which is called?

2.nullptrの適用シーン
2.1コンパイラ
コンパイラがnullptrをサポートしている場合は、NULLのマクロ定義の代わりにnullptrを直接使用する必要があります.正常に使用する過程で彼らは完全に等価です.コンパイラの場合、Visual Studio 2010はnullptrを含むC++0 xのほとんどの特性をサポートし始めました.VS 2010以前のバージョンでは、このキーワードはサポートされていません.Codeblocks10.5付属のG++4.4.1 nullptrはサポートされていません.4.6.1にアップグレードするとnullptrをサポートできます(-std=c++0 xコンパイルオプションまたは-std=c++11をオンにする必要があります).
2.2使用方法
0(NULL)とnullptrは、次の例でスワップできます.
int* p1 = 0;  
int* p2 = NULL;
int* p3 = nullptr;  
  
if(p1 == 0) {}  
if(p2 == 0) {}  
if(p3 == 0) {}
if(p1 == nullptr) {}  
if(p2 == nullptr) {}  
if(p3 == nullptr) {}  
if(p1 == p2) {}  
if(p2 == p3) {} 
if(p1) {}
if(p2) {}
if(p3) {}

次の例ではnullptrを整形に割り当てることはできません.
int n1 = 0;             // ok 
int n2 = NULL;          //warning 
int n3 = nullptr;       // error  
int n4 = (int)NULL;     //ok
int n5 = (int)nullptr;  //error
  
if(n1 == nullptr) {}    // error  
if(n2 == nullptr) {}    // error  
if(nullptr) {}          // error  
nullptr = 0             // error

nullptrはNULLよりも厳しいことがわかります.
上記のリロードの問題はnullptrを使用するとchar*が呼び出されます.
void foo(int)   {cout << "int" << endl;}  
void foo(char*) {cout << "pointer" << endl;}  
  
foo(0);       // calls foo(int)  
foo(nullptr); // calls foo(char*)

3.シミュレーションnullptrの実現
一部のコンパイラでは、c++11の新しいキーワードnullptrがサポートされていません.nullptrを実装するシミュレーションもできます.
const  
class nullptr_t_t  
{  
public:  
    template<class T>           operator T*() const {return 0;}  
    template<class C, class T>  operator T C::*() const { return 0; }  
private:  
    void operator& () const;  
} nullptr_t = {};  
#undef NULL  
#define NULL nullptr_t