ポインターがメモリアドレスを保持しているだけだと思いましたか?
はい。ただし、そのメモリ アドレスを使用することは許可されています。特に C++ では、「ポインタ演算」と呼ばれるものが許可されています。これにより、メモリ アドレスを使用して、既にアドレスを持っているメモリに関連する他のメモリのアドレスを取得できます。たとえば、メモリアドレスがある場合、その直後にあるメモリのアドレスを取得できます。
(四角は記憶場所)
☐
☐
☐ ← I have the address of this memory in variable A
☐ ← I would like to get the address of this memory location and to store it in X
☐
☐
☐
int *A = ...;
int *X = A + 1; // compute the address of the next memory location
したがって、配列は一連のメモリ位置です。配列の要素にアクセスするには、持っているアドレスを取得し、アクセスしたい要素のアドレスを計算してから、その新しいアドレスを使用します。
int *A = new int[10];
int *X = A + 5; // get the address of the memory five locations past where A points to
*X = 999;
計算したアドレスを変数に格納する必要はありません。
int *A = new int[10];
*(A+5) = 999;
C++ は、構文 の省略形を提供します*(A+5)
。これは、配列インデックス演算子です。
int *A = new int[10];
A[5] = 999;
興味深い点の 1 つは、配列インデックス演算子が実際にはこの*(A+5)
式の省略形にすぎないことです。オペランドを反転して行う*(5+A)
ことができるので、配列インデックス演算子でも同じことができます。
5[A] = 999;
ただし、あまり読みにくいため、これを行うべきではありません。
ポインターについて知っておくべきもう 1 つのこと: Java にはポインターがあります。あなたがするとき
String s = new String();
Java ではs
ポインタです。Java は、この事実を隠そうとするだけでなく、C++ よりもはるかに多くのポインターを使用する必要があります。Java にはポインター演算がなく、C++ のように Java でポインターを手動で逆参照する必要はありません。ただし、次のことを考慮してください。
List<String> l = new List<String>();
List<String> m = l; // Do I have two lists, l and m, that can be modified independently? Or do I have two entities, l and m, that both refer to the same List object?
そして、Java で発生する Null Pointer 例外を思い出してください。
Java を使用している場合は、既にポインターを使用しています。C++ ではそれほど違いはありませんが、C++ では、Java のように不十分に隠されるのではなく、直接可視で明示的です。