C++ 参照とポインタの比較
参照は C++ における概念で、初心者は参照とポインタを混同しやすいです。
以下のプログラムでは、n は m の参照(reference)であり、m は被参照オブジェクト(referent)です。
int m; int &n = m;
n は m の別名(あだ名)に相当し、n に対するあらゆる操作は m に対する操作です。
したがって、n は m のコピーでもなく、m を指すポインタでもなく、実際には n は m 自身です。
参照の規則:
- (1)参照は作成と同時に初期化されなければなりません(ポインタはいつでも初期化できます)。
- (2)NULL 参照は存在できません。参照は正当な記憶域と関連付けられなければなりません(ポインタは NULL でもかまいません)。
- (3)参照は一度初期化されると、参照の関係を変更できません(ポインタはいつでも指すオブジェクトを変更できます)。
以下のサンプルプログラムでは、k は i の参照として初期化されています。
文 k = j は k を j の参照に変更するのではなく、単に k の値を 6 に変更するだけです。
k は i の参照であるため、i の値も 6 になります。
int i = 5; int j = 6; int &k = i; k = j; // k 和 i 的值都变成了 6;
参照の主な機能は、関数の引数と戻り値を渡すことです。
C++ 言語では、関数の引数と戻り値の受け渡し方法は3つあります:値渡し、ポインタ渡し、参照渡しです。
以下は「値渡し」のサンプルプログラムです。
Func1 関数体内の x は外部変数 n のコピーであるため、x の値を変更しても n には影響しません。したがって、n の値は依然として 0 です。
void Func1(int x)
{
x = x + 10;
}
...
int n = 0;
Func1(n);
cout << "n = " << n << endl; // n = 0
以下は「ポインタ渡し」のサンプルプログラムです。
Func2 関数体内の x は外部変数 n を指すポインタであるため、そのポインタの内容を変更すると n の値が変わります。したがって、n の値は 10 になります。
void Func2(int *x)
{
(* x) = (* x) + 10;
}
...
int n = 0;
Func2(&n);
cout << "n = " << n << endl; // n = 10
以下は「参照渡し」のサンプルプログラムです。
Func3 関数体内の x は外部変数 n の参照であり、x と n は同じものです。x を変更することは n を変更することに等しいため、n の値は 10 になります。
void Func3(int &x)
{
x = x + 10;
}
...
int n = 0;
Func3(n);
cout << "n = " << n << endl; // n = 10
上記の3つのサンプルプログラムを比較すると、「参照渡し」の性質は「ポインタ渡し」に似ており、記述方法は「値渡し」に似ていることがわかります。
実際には「参照」でできることはすべて「ポインタ」でもできます。なぜ「参照」というものが必要なのでしょうか?
答えは「適切な道具でふさわしい仕事をする」ことです。
ポインタはメモリ内のあらゆるものを制約なく操作できます。ポインタは強力ですが、非常に危険です。
本当にあるオブジェクトの「別名」を借りるだけでよい場合は、「ポインタ」ではなく「参照」を使用してください。事故を防ぐためです。