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 ポインタ:通常は参照、「何も指さない可能性がある」ならポインタ

📝 練習問題

  1. 初級(難易度 ⭐): 関数 void addTen(int& x) を書いてください。引数の変数に10を加算。main でテスト。

  2. 中級(難易度 ⭐⭐): 関数 void swap(int& a, int& b) を書いてください。2つの変数の値を交換。main でテスト。

  3. 上級(難易度 ⭐⭐⭐): プログラムを書いてください。「3つの数をソート」を実装:

    • 関数 void sortThree(int& a, int& b, int& c) を書き、昇順にソート
    • main でユーザー入力、sortThree を呼び出し、ソート後の結果を出力


6. 🚀 次のステップ

参照との違いを理解したら、次は 動的メモリ(レッスン26) —— newdelete でメモリを管理、ヒープとスタックを理解しよう!

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%