C / C ++での参照とポインタの関係と違い
C / C ++でポインターを使用する必要があるのはなぜですか?
1.すべてのプログラミング言語はポインターを使用します。C++はユーザー(プログラマー)にポインターを公開しますが、JAVAやC#などの言語はポインターを非表示にします。
2.ポインタは、データ構造を効果的に表すことが
できます。3。メモリを動的に割り当てて、メモリの自由な管理を実現できます
。4。文字列を使用して配列を効率的に使用するのに便利です
。5。ポインタは、次のようなデータのストレージアドレスに直接関連しています。効率的です。値の転送では、最初に実際のパラメーターのアドレスから値を取得し、次に値を仮パラメーターに割り当てて関数の計算に使用します。また、ポインターは、仮パラメーターのアドレスを直接実パラメーターのアドレスにポイントし、使用時にデータを直接フェッチするため、特に頻繁な割り当てで効率が向上します。その他の場合(注:仮パラメーターの変更は実際のパラメーターに影響します!)
参照とポインタの違いは?
導入のプレーンな言葉を最初に:
ポインタ -タイプTのために、Tがポインタ型Tで、Tのある、型変数は、オブジェクトTのアドレスを保持することができ、そしてTは、あなたには、いくつかの修飾子を追加することができますタイプですconst、volatileなどなど 下の図と、示されているポインタの意味を
参照してください。Reference -Referenceはオブジェクトのエイリアスであり、主に関数パラメーターと戻り値の型に使用されます。記号X&は、型Xの参照を示します。下の図、引用符の意味をご覧ください。
- ポインタは、アドレスが指す値を変更でき、他のアドレスも指すことができます。また、参照は、初期化時に指定されたオブジェクトを常に指しますが、オブジェクトの値を変更できます
- メモリ割り当ての観点から、プログラムはポインタ変数にメモリ領域を割り当てますが、リファレンスには割り当てません。これは、既存のオブジェクトを指すように、宣言時にリファレンスを初期化する必要があるためです。参照はnull値を指すことはできません。
- コンパイルの観点から、プログラムはコンパイル中にシンボルテーブルへのポインターと参照を追加し、シンボルテーブルは変数名と変数に対応するアドレスを記録します。ポインタでシンボルテーブルアドレス値に対応する可変ポインタ変数のアドレス値と、に対応するシンボルテーブル基準アドレス値の参照先オブジェクトのアドレス値。シンボルテーブルが生成された後は変更されないため、ポインターはポイントされたオブジェクトを変更でき(ポインター変数の値を変更できます)、参照されているオブジェクトは変更できません。これが、ポインタの使用が安全ではなく、参照セキュリティを使用する主な理由です。ある意味では、参照はアドレスを変更できないポインタと考えることができます。
- null値への参照がないという事実は、参照を使用するコードがポインターを使用するよりも効率的であることを意味します。参照を使用する前に、その有効性をテストする必要がないためです。代わりに、ポインターを常にテストして、ポインターが空にならないようにする必要があります。
- 理論的には、ポインターレベルの数に制限はありませんが、参照は1レベルのみです。次のように:
int ** p1; //合法。ポインターへのポインター
int *&p2; //正当。ポインター
int への参照&* p3; //不正。参照へのポインタは不正です
int && p4; //不正です。
上記の参照は左から右であることに注意してください。
要するに、「ポインタはメモリの一部を指し、その内容は指し示されたメモリのアドレスであり、参照は特定のメモリのエイリアスであり、参照はポインティングを変更しない」と結論付けることができます。
特別な定数
int main()
{
int i= 0;
int j=1;
//常量引用,指向的地址的内容是个常量,不可以修改,即i的值不可以修改
const int &r = i ;
//常量指针,p指针的地址可修改,但无法修改指向地址的内容,*p不可修改,即p指针不可以修改j的值,但可以指向i的地址
const int* p=&j;
p = &i;
//指针常量,q指向的地址不可修改,可以修改指向地址的内容,*q可以修改,即q指针只能指向j的地址,但可以修改j的值
int* const q = &j;
*q=5;
//常量指针常量,w指向的地址和内容都不可修改,即w和*w均不可修改
const int* const w = &j;
cout<<j<<endl;
cout<<i<<endl;
return 0;
}
ポインタの受け渡しと参照の受け渡し
- ポインタ転送パラメータは基本的に値転送の方法であり、彼が渡すのはアドレス値です。値の転送プロセスでは、呼び出された関数の仮パラメーターは、呼び出された関数のローカル変数として扱われます。つまり、メモリ空間がスタック上で開かれ、呼び出し関数によって入力された実際のパラメーターの値が格納され、実際のパラメーターのコピーになります。 。値転送の特徴は、仮パラメーターで呼び出された関数の操作がローカル変数として実行されることです。これは、呼び出し関数の実際のパラメーター変数の値には影響しません。
- 参照渡しのプロセスでは、呼び出された関数の仮パラメーターもローカル変数としてスタック上のメモリー空間を開きますが、このとき、呼び出し関数によって入力された実際のパラメーター変数のアドレスが格納されます。仮パラメータで呼び出された関数の操作はすべて間接アドレッシングに処理されます。つまり、呼び出し関数の実際のパラメータ変数は、スタックに格納されたアドレスを介してアクセスされます。このため、仮パラメーターで呼び出された関数の操作は、呼び出し関数の実際のパラメーター変数に影響します。
参照の受け渡しとポインターの受け渡しは異なります。これらはすべて、呼び出された関数のスタックスペース上のローカル変数ですが、参照パラメーターの処理はすべて、間接アドレス指定メソッドを介して呼び出し側関数の関連する変数に作用します。ポインターによって渡されるパラメーターの場合、呼び出された関数のポインターアドレスが変更されても、呼び出し元の関数の関連変数には影響しません。ポインターパラメーターを渡すことにより、呼び出し元の関数内の関連する変数を変更する場合は、ポインターへのポインター、またはポインター参照を使用する必要があります。
まとめ
最後に、ポインタと参照の類似点と相違点をまとめます:
★類似点:
- すべてがアドレスの概念であり、
ポインタはメモリの一部を指し、その内容は指し示されたメモリのアドレスであり、参照はメモリの一部のエイリアスです。
★違い: - ポインタはエンティティであり、参照は個別の名前にすぎません。
- 参照は定義時に一度しか初期化できず、その後不変になります。ポインタは可変です。参照は「一方から他方へ」、ポインタは「異なると考える」ことができます。
- 参照にはconstがなく、ポインタにはconstがあり、constポインタは不変です。
具体的には、int&const aのような形式はなく、const int&aは存在します。この形式では、後者のガイドラインの値は変更できません) - 参照をnullにすることはできません。ポインタはnullにすることができます。
- 「参照のサイズ」はポイントされた変数(オブジェクト)のサイズであり、「サイズのポインタ」はポインタ自体のサイズです4
- ポインタと参照インクリメント(++)演算の意味は異なります。
- 参照はタイプセーフであり、ポインタはそうではありません(参照には、ポインタよりも多くの型チェックがあります)