2012-07-10 13 views
8

私はC++のFAQ読んでいた - 「8.6 - When should I use references, and when should I use pointers?」と特にこの文:C++に "NULL参照"がないのはなぜですか?

使用参照することができます、とポインタあなたがする必要があります。オブジェクトを参照していない参照 - 関数のパラメータまたは戻り値が「センチネル」の参照を必要とする場所

...

上記の例外があります。これは、通常、ポインタを返す/取ることによって最もよく行われ、NULLポインタにこの特別な意味を与えます(参照は、逆参照されたNULLポインタではなく、オブジェクトのエイリアスでなければなりません)。

私が見たことから、 "センチネル"参照の必要性は、しばしば参照の代わりにポインタを使用する理由です。私が疑問に思っているのは、なぜC++に参照用の特別な "NULL値"がないのですか?それは多くの問題を解決するポインタをほとんど不要にするだろうと思われる。

なぜ、それは言語仕様の一部ではありませんでしたか?

編集:

私は私の質問がクリアされているかわからない - 私はNULL参照についてlitterally求めていませんよね。ほとんどの場合、私はC++で "参照はオブジェクトです"と読みます。そして、ほとんどのOOP言語では、オブジェクトはNULL(パスカル、C#、Java、JavaScript、PHPなど)で、これらのすべてでsomeObject = nullまたはsomeObject := nilを実行できます。実際には、Pascalもポインタをサポートしていますが、オブジェクトはnilです。だから、C++は何とか特別なもので、NULLオブジェクトを持たないのはなぜですか?見落としや実際の決定だったのでしょうか?

+1

ポインタが必要なことをどのように取り除くのかを教えてください。 –

+3

@nathanwhiteしたがって、参照は構文的に砂糖になります。おそらく、ポインタはいつでも使用できます。 IMOは、参照の利点の一部を完全に削除します。 – hvd

+4

[C++にポインタと参照の両方があるのはなぜですか?](http://www2.research.att.com/~bs/bs_faq2.html#pointers-and-references)と[C++:nullリファレンス](http: /stackoverflow.com/questions/4364536/c-null-reference)。 –

答えて

13

リファレンスは意味のない有効なメモリアドレスを指しているため、逆参照は安全/定義されているので、NULLチェックは必要ありません。参照はデザインによって再割り当てすることはできません。

varがNULLで、クライアントコードがそのケースを処理する必要がある場合は、ポインタを使用します。有効/初期化されたメモリアドレスを保証できる場合は、参照を使用します。

ポインタを使用する1つの例は、クラス構築時に知られていない、または初期化可能なインスタンスへの「参照」を格納するクラスのメンバです。ただし、メンバ参照は(初期化子リストを介して)構築時に初期化されなければならず、その割り当ては延期できません。あなたはそれがその後、構文以外のポインタに違いはありませんnull参照を許可した場合

(同じNULLチェックが場所を取る必要があります。)

更新:

「と、中Pascal、C#、Java、JavaScript、PHPなど[NULL]になる可能性があります。 ?NULLオブジェクト 『が、これらのオブジェクト参照は、多かれ少なかれ簡単な構文とC++のポインタのようなもので、「私はあなたがの印象を与えるかもしれない、この。JavaやC#などについて、少し混乱していると思います

』 GC計測および例外投げ。これらの言語では、あなたが「ヌルオブジェクト」を操作する場合は、とNullReferenceException(C#の)のような例外のいくつかの種類を取得します。地獄、JavaでそのNullPointerExceptionがと呼ばれる。

をあなたは持っていますあなたがそれらを安全に使う前にnullをチェックする。C++ poiのようなもの(ほとんどの管理された言語を除いて、ポインタはデフォルトでNULLに初期化されますが、C++では通常は初期ポインタ値を設定します。

  • が必要な場合、あなたは、NULLをチェックしてくださいどのように行うには、プレーンポインタを使用します。

    C++ビューは、選択を有するので、冗長であることについてです。

  • コンパイラが強制する有効性の意味/制約を持つ参照を使用します。
  • 簿記を行うスマートポインタをロールし、必要に応じて行動します。
  • 必要であれば、型が指定されていないメモリブロックを参照するためには、voidポインタ(慎重に!)を使用してください。
+2

Nit:ヌルポインタと初期化されていないポインタは、2つの異なるものです。初期化されていないポインタは、少なくとも確実には検出できません。これは、有効なオブジェクトを含むどこにでも指すことができるためです。 – hvd

+0

@hvdありがとうございました。初期化されていないので、私は本当にNULLを意味しました。ポインターの使い分けを説明するためのセクションを追加しました。 –

0

参照は何かを参照する必要があるため、参照は使用できません。
Cには参照がなく、この言語のポインタしか使用できないため、これはC言語との互換性です

1

参照定義は、別の変数またはオブジェクトと関連付ける必要があります。したがって、空またはnullの参照種別は、存在の目的に違反します。

技術的には、null参照で始まり、ある変数に割り当てるか、後で別の変数に代入することができます。これは、単にどのような参照が作成されることを意図したものではありません。

参照が単純に複製できないその他の用途がいくつかあります。ポインタを使用して小さな量の複雑なデータ(一連のバイト)を参照し、必要なだけ頻繁にポインタに8バイト程度しか費やさずに渡すなど、同じメモリを浪費することなく、参照でそれを行うことはできません。

参照は、常にポインタを使用しない型に結び付けられます。

+0

最初の2段落は正しいです。最後のものには意味がありません。 – wandalen

+0

私は間違いなくここで正確に精緻化されているかどうかを念頭に置いたユースケースを持っていました。しかし、精緻化や意見がなくても、単に「意味を持たない」という言葉は、もっと役に立たず、重みがない。 – fayyazkl

6

ポインタとリファレンスの違いを見てください。標準ではリファレンスがどのように実装されているのかは現時点では常にポインタとして実装されています。

これらの主な違いは、a)セマンティクスb)ポインタを再配置できることc)ポインタがnullでもかまいません。

簡単な答えは、これは意図的に行われたことです。プログラマが参照を参照するときには、a)その参照が設定されていること、(b)変更されないこと(c)オブジェクトと同じセマンティクスで参照を使用できること)を知っておく必要があります。

標準ではnull参照が許可されますか?参照を使用する前にnullをチェックする必要がありましたが、これは望ましくありませんでした。

編集:

あなたの編集については、私はここで混乱が最も単純なオブジェクト指向言語は何が起こっているかを隠しているという事実から生じるかもしれませんね。 Javaを例に取ると、NULLオブジェクトを持っているように見えますが、それらを割り当てることはできません。本当に起こっているのは、Javaにポインタだけがあり、それらのポインタにNULL値を割り当てることができるということです。実際にJavaで直接オブジェクトを持つことは不可能なので、ポインタのセマンティクスを取り除き、ポインターをオブジェクトとして扱います。 C++は単純により強力で、エラーが発生しやすい(Javaの愛好家は、スタックユーザークラスインスタンスは不要で、Javaでそれらを持たないという決定は、複雑さを軽減し、Javaを使いやすくするために行われた)。また、Javaにはオブジェクトがないため、参照はありません。しかし、実際には役に立たないのは、C++の人がポインターの値渡しを参照渡しと呼ぶものをJavaが呼び出すことです。

+0

私は自分の質問を更新した。ほとんどすべてのオブジェクト指向言語が 'null'参照を許しているが、C++はそうではないことをどのように説明しますか?これらの他のすべての言語では、必ずNULLをチェックする必要はありません。完全にコンテキストに依存します。 –

+3

多くのOO言語はわかりませんが、私はそれに反対します。 Javaには参照がなくても、別の構文でも、Javaにはポインタしかありません(たとえば、nullでも構いません)。 Javaには参照がない理由の1つは、Javaにもスタック変数(組み込み型が不足している)がないことです。すべてがヒープであり、すべての変数がポインタであるため、null、スタック・メモリ、不要参照。 vbaも同じです。それは私が知っているほど多くのOO言語です。 – Cookie

+2

C++での参照の典型的な使用例:大きなスタック割り当て変数があり、valueの代わりに参照渡しが必要な場合。ここでは、真のC++参照を使用する必要があり、そうでなければ、nullでなく変更されないためです。 Javaでは、スタック変数を持つことはできません。そのため、呼び出し環境には常にポインターしかないため、参照渡しの構造体は必要ありません。 Javaの人々が「参照渡し」と呼ぶものは、C++の人々が実際に「ポインタで渡す」という混乱がしばしばあります。 – Cookie

1

C++リファレンスは、他のほとんどの言語でこの用語を使用しているという意味での参照ではありません。それはエイリアスのようなものです。 C++リファレンスを使用しても、ポインタの参照を解除するのと同じ方法で「参照解除」する必要はありません。事実上、オブジェクトに割り当てられています。

ヌルオブジェクトインスタンスのようなものは実際にはありません。そのため、このようなことに対するC++リファレンスを作成することはできません。他の言語では、ヌル参照はC++のヌルポインタに相当します。実際には何も含まれていません。

あなたの他の考え方について:1. nullableな参照を持つことは良いです私の心にもの;それは、あなたがどこにいてもヌルをチェックする必要がなく、参照渡しのすべての利点を得ることを意味します。 2. null可能な参照はポインタを置き換えません...メモリやIOの作業を低レベルで行う必要がある場合は、メモリとメモリマップされたデバイスへの生のアクセスが必要になります。 C#(またはC++/CLR)を参照することができます.C#(またはC++/CLR)は、管理された参照と管理されていないポインタを持っています。

関連する問題