CとC++でNULLポインタの定義が異なるのはなぜですか?
疑問点
C言語では
NULL
は次のように定義されます。
(void *)0
であるのに対し,C++では
0
. なぜ、そうなるのでしょうか?
C言語では、もし
NULL
がタイプキャストされないと
(void *)
にタイプキャストされていない場合、コンパイラは警告を生成するかもしれませんし、生成しないかもしれません。これ以外に何か理由があるのでしょうか?
どのように解決するのですか?
C++03 の頃、ISO 仕様 (§4.10/1) でヌルポインタは次のように定義されていました。
ヌルポインタ定数は、ゼロに評価される整数型の積分定数式(5.19)rvalueである。
このため、C++では、次のように書くことができます。
int* ptr = 0;
C言語では、このルールは似ていますが、少し違います(§6.3.2.3/3)。
値0を持つ整数定数式、または型にキャストされたそのような式は
void *
55) ヌルポインタ定数をポインタ型に変換すると、ヌルポインタと呼ばれる結果のポインタは、不等間隔で比較されることが保証される。 55) ヌルポインタ定数をポインタ型に変換した場合,結果として得られるポインタはヌルポインタと呼ばれ,あらゆるオブジェクトやポインタと不等間隔で比較されることが保証されている。 は、任意のオブジェクトまたは関数へのポインタと比較することが保証されています。
その結果、両方の
int* ptr = 0;
と
int* ptr = (void *)0
は合法です。 しかし、私の推測では
void*
のようなステートメントが合法になるように、キャストがここにあるのだと思います。
int x = NULL;
は、ほとんどのシステムでコンパイラの警告を出します。 C++では、これは合法ではありません。
void*
を暗黙のうちに別のポインタ型に変換することはできないからです。 たとえば、これは違法です。
int* ptr = (void*)0; // Legal C, illegal C++
しかし、これは、コード
int x = NULL;
は合法的な C++ です。 このため、C++11 以降では、キーワード
nullptr
はヌルポインタを表します。
int* ptr = nullptr;
これには上記のような問題はありません。
のもう一つの利点は
nullptr
は、C++の型システムでよりよく動作するという利点もあります。 例えば、以下の2つの関数があるとします。
void DoSomething(int x);
void DoSomething(char* x);
もし私が
DoSomething(NULL);
と同等です。
DoSomething(0);
を呼び出すと
DoSomething(int)
の代わりに、期待される
DoSomething(char*)
. しかし
nullptr
では
DoSomething(nullptr);
そして、それは
DoSomething(char*)
関数を期待通りに呼び出します。
同じように、仮に私が
vector<Object*>
があり、各要素をヌルポインタに設定したいとします。 このとき
std::fill
アルゴリズムを使って、私は
std::fill(v.begin(), v.end(), NULL);
しかし、これはコンパイルできません。なぜなら、テンプレートシステムは
NULL
を
int
であり、ポインタではありません。 これを修正するには、次のように記述する必要があります。
std::fill(v.begin(), v.end(), (Object*)NULL);
これは醜いもので、テンプレート・システムの目的をやや破っています。 これを修正するために、私は
nullptr
:
std::fill(v.begin(), v.end(), nullptr);
また
nullptr
はヌルポインタに対応する型を持っていることが知られています(具体的には
std::nullptr_t
のようなもの)、これは正しくコンパイルされます。
これが役に立つことを願っています。
関連
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] JavaScriptのnullとundefinedの違いは何ですか?
-
[解決済み] C++11の'typedef'と'using'の違いは何ですか?
-
[解決済み】高放射能環境下で使用するアプリケーションのコンパイルについて
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】coutはstdのメンバではない
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】C++の余分な資格エラー
-
[解決済み】システムが指定されたファイルを見つけられませんでした。