logo

C++ におけるポインターと参照

前提条件: ポインタ 参考文献

C および C++ はポインターをサポートします。これは、Java、Python、Ruby、Perl、PHP などの他のほとんどのプログラミング言語とは異なり、参照のみをサポートします。しかし興味深いことに、C++ はポインターとともに参照もサポートしています。



表面的には、参照とポインタはどちらも、ある変数に別の変数へのアクセスを提供するために使用されるため、非常によく似ています。どちらも多くの同じ機能を提供するため、これらのメカニズムの違いが不明瞭になることがよくあります。この記事では、ポインターと参照の違いを説明していきます。

ポインタ : ポインタは、別の変数のメモリ アドレスを保持する変数です。ポインタは、 * 演算子が指すメモリ位置にアクセスします。

参考文献 : 参照変数はエイリアス、つまり既存の変数の別の名前です。ポインタと同様に、参照もオブジェクトのアドレスを格納することによって実装されます。
参照は、自動間接化を備えた定数ポインター (定数値へのポインターと混同しないでください!) と考えることができます。つまり、コンパイラーは、 * あなたのためのオペレーター。



int i = 3;   // A pointer to variable i or 'stores the address of i' int *ptr = &i;   // A reference (or alias) for i. int &ref = i;>

違い :

1. 初期化: ポインタは次の方法で初期化できます。

int a = 10; int *p = &a; // OR  int *p; p = &a;>

ポインタの宣言と初期化は同じステップまたは複数行で行うことができます。



2. 参考文献の中では、

int a = 10; int &p = a; // It is correct // but int &p; p = a; // It is incorrect as we should declare and initialize references at single step>

注記: この違いはコンパイラによって異なる場合があります。上記の違いは Turbo IDE に関するものです。

3. 再割り当て: ポインタは再割り当てできます。このプロパティは、リンク リスト、ツリーなどのデータ構造の実装に役立ちます。次の例を参照してください。

int a = 5; int b = 6; int *p; p = &a; p = &b;>

4. 一方、参照は再割り当てできず、初期化時に割り当てる必要があります。

ランタイムエラー
int a = 5; int b = 6; int &p = a; int &p = b; // This will throw an error of 'multiple declaration is not allowed'  // However it is valid statement, int &q = p;>

5. メモリアドレス: ポインタはスタック上に独自のメモリ アドレスとサイズを持ちますが、参照は元の変数と同じメモリ アドレスを共有し、スタック上のスペースを占有しません。

int &p = a; cout << &p << endl << &a;>

6. NULL値: ポインタには NULL を直接割り当てることができますが、参照には NULL を割り当てることはできません。参照に関連付けられた制約 (NULL なし、再割り当てなし) により、基礎となる操作で例外状況が発生しないことが保証されます。

7。 間接: 参照では 1 レベルの間接化しか提供されないのに対し、追加レベルの間接化を提供するポインタ間 (ダブル ポインタと呼ばれる) を使用できます。例えば、

In Pointers, int a = 10; int *p; int **q; // It is valid. p = &a; q = &p;  // Whereas in references, int &p = a; int &&q = p; // It is reference to reference, so it is an error>

8. 算術演算: ポインターに対してはさまざまな算術演算を実行できますが、参照演算と呼ばれるものはありません (ただし、&obj + 5 のように、参照によって指定されたオブジェクトのアドレスに対してポインター演算を実行することはできます)。

C++ における参照とポインターの違いを表形式で示したもの

参考文献 ポインタ
再割り当て リファレンスでは変数を再代入することはできません。 変数はポインターで再割り当てできます。
メモリアドレス 元の変数と同じアドレスを共有します。 ポインタは独自のメモリ アドレスを持っています。
仕事 別の変数を参照しています。 変数のアドレスを格納しています。
Null値 null 値はありません。 値を null として割り当てることができます。
引数 この変数は、値渡しメソッドによって参照されます。 ポインタは、参照渡しとして知られる方法で機能します。

いつ何を使うか

参照がポインターとして内部的に実装されているため、パフォーマンスはまったく同じです。ただし、いつ何を使用するかを決定するために、いくつかの点に留意することができます。

  • 参照を使用します。
    • 関数のパラメータと戻り値の型。
  • ポインタを使用します。
    • ポインター算術演算または NULL ポインターの受け渡しが必要な場合。たとえば、配列の場合です (配列へのアクセスはポインター演算を使用して実装されることに注意してください)。
    • リンクされたリスト、ツリーなどのデータ構造とそのアルゴリズムを実装します。これは、異なるセルを指すために、ポインターの概念を使用する必要があるためです。

C++ FAQ Lite で引用 : 可能な場合は参照を使用し、必要な場合はポインタを使用します。再装着する必要がない場合は、通常、ポインタよりも参照の方が優先されます。これは通常、参照がクラスのパブリック インターフェイスで最も役立つことを意味します。通常、参照はオブジェクトのスキンに表示され、ポインタは内部に表示されます。

上記の例外は、関数のパラメーターまたは戻り値にセンチネル参照 (オブジェクトを参照しない参照) が必要な場合です。これは通常、ポインタを返したり受け取ったりして、nullptr 値にこの特別な意味を与えることによって最もよく行われます (参照は、逆参照された null ポインタではなく、常にオブジェクトのエイリアスでなければなりません)。

関連記事:
いつ引数を参照またはポインタとして渡すのでしょうか?