C++における参照
ポインタは[強力ではあるが]、[使い方が少し面倒だ]――[「reference」と記述する必要があり]、[さらに]nullポインタにも注意しなければならない。
C++では参照(Reference)が導入されました。これは変数の「別名」であり、ポインタよりも[安全]で[簡潔]に使用できます。
1. リファレンスとは何ですか?
(1) 1.1 [日常生活における]参考例
| [生活シーン] | 番組[での対応] |
|---|---|
| [あだ名]「[小明]」、[どちらの名前で呼んでも見つかる] | 参照(変数[の別名]) |
| [身分証に記載されている名前と普段使っている名前] | reference[和原]variable |
参照[の本質]: 参照[とは]変数[の][別名]である――[参照に対する]操作[は、][その参照される]変数[に対する]操作[に他ならない]。
(2) 1.2 なぜ参照が必要なのか?
[用]ポインタ([面倒]):
▶ サンプル 2: codeexample (難易度 ⭐)
#include iostream
void modifyValue(int* x) {
*x = 100; // ...
}
int main() {
int a = 5;
modifyValue(&a); // ...
std::cout << a << std::endl; // 100
return 0;
}
[用]参考([簡単]):
#include iostream
void modifyValue(int& x) { // x reference
x = 100; //,
}
int main() {
int a = 5;
modifyValue(a); //,
std::cout << a << std::endl; // 100
return 0;
}
2. 参照変数の宣言と初期化
(1) 2.1 参照の宣言
[文法]:
& = ;
例:
#include iostream
int main() {
int x = 5;
int& ref = x; // ref x 's
std::cout << "x = " << x << std::endl; // 5
std::cout << "ref = " << ref << std::endl; // 5
ref = 100; // ref x
std::cout << "x =" << x << std::endl; // 100
return 0;
}
💡 [重要]: 参照型は[必ず初期化する必要がある]――[先に宣言して]、[後で値を代入する]ことはできない。
(2) 参照とポインタの比較
| [比較] | 参照 | ポインタ |
|---|---|---|
| [文法] | int& ref = x; |
int* p = &x; |
| [空にできるか] | ❌ [できない]([初期化必須]) | ✅ [できる](nullptr) |
| [参照を明記するか] | ❌ [不要]([直接使用]) | ✅ [必要](*p) |
| [再割り当て可能か] | ❌ [不可]([一度バインドすると]、[変更できない]) | ✅ [可能]([別の]変数に割り当て可能) |
| [推奨度] | ⭐⭐⭐⭐⭐([優先的に使用]) | ⭐⭐⭐([必要に応じて使用]) |
3. reference[として]function[引数]*
(1) 3.1 [基本的な使い方]
#include iostream
// ""
void minMax(int arr, int length, int& min, int& max) {
min = arr[0];
max = arr[0];
for (int i = 1; i < length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
}
int main() {
int arr[5] = {3, 1, 4, 1, 5};
int min, max;
minMax(arr, 5, min, max); // min and max modify
std::cout << ":" << min << std::endl; // 1
std::cout << ":" << max << std::endl; // 5
return 0;
}
💡 [要点]: 参照型引数を持つ関数は、[複数の]値を[返す]ことができます([複数の]参照型引数を変更できるため)。
(2) 3.2 const 参照([最もよく使われる])
[関数にパラメータを変更させたくない]が、[コピーにかかるオーバーヘッドを避けたい]場合は、const参照を使用できます。
#include iostream
#include string
void printName(const std::string& name) { // const reference:modify name
std::cout << ":" << name << std::endl;
// name = "Alice"; // ❌:modify const reference
}
int main() {
std::string myName = "MOTO";
printName(myName); //,
return 0;
}
💡 [黄金律]: 関数[引数優先] const 参照——[安全性と効率性を両立]。
4. 参照[の落とし穴]*
(1) 4.1 参照[必須]初期化 *
#include iostream
int main() {
int& ref; // ❌:reference
return 0;
}
コンパイルエラー[詳細]:
error: 'ref' declared as reference but not initialized
(2) 4.2 参照[再バインド不可]*
#include iostream
int main() {
int x = 5;
int y = 10;
int& ref = x;
ref = y; // ❌ bind! x 'svalue y 'svalue
std::cout << "x = " << x << std::endl; // 10
std::cout << "y = " << y << std::endl; // 10
return 0;
}
💡 [重要]: 参照は[一度特定の]変数にバインドされると、[別の]変数に[再バインドすることはできない]**。
5. 演習:[複数の戻り値]value*
▶ サンプル 1: [商と余りの計算] (難易度 ⭐⭐)
#include iostream
// ""
void divide(int a, int b, int& quotient, int& remainder) {
quotient = a / b;
remainder = a % b;
}
int main() {
int a = 17, b = 5;
int q, r;
divide(a, b, q, r); // q and r modify
std::cout << a << " / " << b << " = " << q << " ... " << r << std::endl;
// output:17 / 5 = 3 ... 2
return 0;
}
❓ よくある質問
Q:reference[と]pointer[には一体どのような違いがある]? A:> - reference[は]変数[の][別名]であり、pointer[はアドレスを格納する]変数である > - reference[は初期化が必要]だが、pointer[は初期化されなくてもよい]
nullptr> - 参照変数は[再割り当てできない]が、ポインタ変数は[再割り当てできる] > - [優先して]参照変数を使うが、[「なし」を表す必要がある場合]([その場合は]ポインタ変数を使う) Q:[なぜ]配列を[引数として渡す際]、[参照変数を使えない]のですか? A:[使うことはできる]が、[arrayreference]という構文で記述する必要がある([やや複雑])。[もっと簡単な方法]:
std::array[または]std::vectorを使用する([後ほど学習します])。
Q:参照型はプログラムの実行効率を向上させることができますか? A:[できません]。参照型は、低レベルでは通常ポインタを使って実装されているため、実行効率はポインタと同じです。
[それが向上させるのは][開発効率](コードが[より簡潔]で、[ミスが起きにくい])。
Q:referencesについて最も重要なことは何ですか? A:まず核心概念を理解し、その後実践的な例で練習することが重要です。
📖 まとめ
- 参照[は]変数[の]「[別名]」であり、[参照に対する]操作は[参照される変数に対する]操作である
- 参照[初期化必須]、[かつ][再バインド不可]
- reference[として]function[の引数]に指定することで、function[が外部の]変数(class[のような]ポインタ)を変更できるようにする
- const参照[は最も一般的な引数渡し方法]——[安全性と効率性を両立している]
- 参照とポインタ:[優先して使用する]参照、[必要な場合に使用する]ポインタ
📝 練習問題
-
初心者(難易度 ⭐): [関数]
void addTen(int& x)を [作成] し、[渡された] 変数に 10 を [加える]。main[内で] [テスト] する。 -
中級(難易度 ⭐⭐): [関数]
void swap(int& a, int& b)を記述し、[2つの]変数の値を[交換]する。main[でテスト]する。 -
上級(難易度 ⭐⭐⭐): [プログラム]を作成し、[「3つの数を並べ替える」]を[実装]する:
-
[関数]
void sortThree(int& a, int& b, int& c)を [作成し、3つの数を小さい順に並べ替える] -
main内で、ユーザーに[3つの数値]を入力させ、sortThreeを呼び出し、[その後]ソートされた結果を出力する -
参照[は]変数[の別名]であり、[宣言時には初期化が必要]
-
参照とポインタ:参照[空にできない]、[再バインドできない]
-
参照[として]関数[引数]:[外部]変数の[変更]、[コピーを回避]
-
const reference[一時的な参照可能]object([延長された]有効期間)
-
参照[戻り値]値[lvalueとして使用可能]
6. 🚀 次は
[学んだ]内容との違いとして、[次は] 動的メモリ[割り当て]([第]26[課])について学習します―― new と delete を使ってメモリを [手動で管理]し、ヒープ[と]スタックについて[理解]します。



