C++: C++ 参照
最終更新:2026-08-31
ポインタは強力ですが、使い方は少し複雑 —— 毎回
*pで間接参照、ヌルポインタのチェックが必要。C++には 参照(Reference) —— 変数の「別名」で、使い方は簡単、ポインタより簡潔です。
1. 参照とは?
(1) 1.1 参照の特徴
| 特徴 | プログラムでの意味 |
|---|---|
| 変数の「別名」 | 参照は変数の別名 |
| 宣言と同時に初期化 | 参照と変数は常に連動 |
| 間接参照不要 | 参照は変数と同じように使う |
参照の定義: 参照は変数の別名 —— 参照を通じて変数の値を操作、参照自体は値を持ちません。
(2) 1.2 なぜ参照が必要?
ポインタを使う場合:
▶ サンプル 2:コード例(難易度 ⭐)
CPP
#include <iostream>
void modifyValue(int* x) {
*x = 100; // 間接参照が必要
}
int main() {
int a = 5;
modifyValue(&a); // アドレスを渡す
std::cout << a << std::endl; // 100
return 0;
}
参照を使う場合:
CPP
#include <iostream>
void modifyValue(int& x) { // xは参照
x = 100; // 直接代入、間接参照不要
}
int main() {
int a = 5;
modifyValue(a); // 変数をそのまま渡す
std::cout << a << std::endl; // 100
return 0;
}
2. 参照の宣言と初期化
(1) 2.1 参照の宣言
構文:
TEXT
📖 参照専用
型& 参照名 = 変数名;
例:
CPP
#include <iostream>
int main() {
int x = 5;
int& ref = x; // refはxの参照
std::cout << "x = " << x << std::endl; // 5
std::cout << "ref = " << ref << std::endl; // 5
ref = 100; // 参照を通じてxを変更
std::cout << "x = " << x << std::endl; // 100
return 0;
}
💡 ヒント: 参照は必ず初期化が必要 —— 初期化しないとコンパイルエラー。
(2) 2.2 参照 vs ポインタ
| 特徴 | 参照 | ポインタ |
|---|---|---|
| 宣言 | int& ref = x; |
int* p = &x; |
| ヌル値 | ❌ 不可(必ず何かを指す) | ✅ 可能(nullptr) |
| 間接参照 | ❌ 不要(変数と同じ) | ✅ 必要(*p) |
| 再代入 | ❌ 不可(一度束縛、変更不可) | ✅ 可能(別の変数を指せる) |
| 安全性 | ⭐⭐⭐⭐⭐(推奨) | ⭐⭐⭐(用途次第) |
3. 参照を関数に渡す
(1) 3.1 基本的な使い方
CPP
#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とmaxが変更される
std::cout << "最小値:" << min << std::endl; // 1
std::cout << "最大値:" << max << std::endl; // 5
return 0;
}
💡 ヒント: 参照で関数に「複数の戻り値」を返せます(参照パラメータを変更)。
(2) 3.2 const 参照(推奨)
関数で修正しないが、コピーを避けたい場合、const 参照を使います。
CPP
#include <iostream>
#include <string>
void printName(const std::string& name) { // const 参照:修正できない
std::cout << "名前:" << name << std::endl;
// name = "Alice"; // ❌ エラー:const 参照は修正不可
}
int main() {
std::string myName = "MOTO";
printName(myName); // コピーなし、安全
return 0;
}
💡 ヒント: 関数の引数には const 参照を推奨 —— コピーを避け、安全性を確保。
4. 参照のよくあるエラー
(1) 4.1 参照を初期化せずに宣言
CPP
#include <iostream>
int main() {
int& ref; // ❌ エラー:参照は初期化が必要
return 0;
}
コンパイルエラー:
TEXT 📖 参照専用error: 'ref' declared as reference but not initialized
(2) 4.2 参照の再束縛
CPP
#include <iostream>
int main() {
int x = 5;
int y = 10;
int& ref = x;
ref = y; // ❌ 再束縛ではない!xの値がyの値になるだけ
std::cout << "x = " << x << std::endl; // 10
std::cout << "y = " << y << std::endl; // 10
return 0;
}
💡 ヒント: 参照は一度束縛したら変数を変えられません、再束縛で別の変数を指すことはできません。
5. 実践例:複数の戻り値
▶ サンプル 1:商と余り(難易度 ⭐⭐)
CPP
#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とrが変更される
std::cout << a << " / " << b << " = " << q << " ... " << r << std::endl;
// 出力:17 / 5 = 3 ... 2
return 0;
}
▶ サンプル 3:const 参照で範囲for文(難易度 ⭐⭐)
CPP
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> words = {"Hello", "World", "C++"};
// const 参照でコピーを避ける
std::cout << "単語: ";
for (const std::string& word : words) {
std::cout << word << " ";
}
std::cout << std::endl;
// コピーせずに総文字数をカウント
int totalChars = 0;
for (const std::string& word : words) {
totalChars += word.length();
}
std::cout << "総文字数: " << totalChars << std::endl;
return 0;
}
出力:
TEXT 📖 参照専用単語: Hello World C++ 総文字数: 13
❓ よくある質問
Q 参照とポインタの使い分けは?
A
- 参照は変数の別名、ポインタはアドレスを格納する変数
- 参照は必ず何かを指す、ポインタは
nullptrになれる - 参照は再束縛不可、ポインタは変更可能
- 関数引数には参照
Q 配列を関数に渡すとき、参照を使える?
A 使えますが、配列の参照の構文は少し複雑。
推奨:
Q 参照はプログラムの効率を上げる?
A はい。参照は内部ではポインタで実装されており、ポインタと同じ効率です。
ただしコードが簡潔
📖 まとめ
- 参照は変数の「別名」、参照を通じて変数の値を操作
- 参照は必ず初期化、再束縛不可
- 参照を関数に渡すと、関数で変数を修正可能(ポインタと同様)
- const 参照は読み取り専用の推奨 —— コピーを避け、安全性を確保
- 参照 vs ポインタ:通常は参照、「何も指さない可能性がある」ならポインタ
📝 練習問題
-
初級(難易度 ⭐): 関数
void addTen(int& x)を書いてください。引数の変数に10を加算。mainでテスト。 -
中級(難易度 ⭐⭐): 関数
void swap(int& a, int& b)を書いてください。2つの変数の値を交換。mainでテスト。 -
上級(難易度 ⭐⭐⭐): プログラムを書いてください。「3つの数をソート」を実装:
- 関数
void sortThree(int& a, int& b, int& c)を書き、昇順にソート mainでユーザー入力、sortThreeを呼び出し、ソート後の結果を出力
- 関数
6. 🚀 次のステップ
参照との違いを理解したら、次は 動的メモリ(レッスン26) —— new と delete でメモリを管理、ヒープとスタックを理解しよう!