C++: 関数のパラメータ
最終更新:2026-08-31
前のレッスンで関数を学んだ。このレッスンでは、データを関数に渡す方法——値渡しと参照渡し——と、それがコードのパフォーマンスと動作にどう影響するかを深く掘り下げる。
1. 値渡し
(1) 1.1 値渡しの仕組み
値渡しでは、引数のコピーがパラメータに作成される。関数内の変更は元の変数に影響しない。
CPP
#include <iostream>
void doubleValue(int x) { // xは引数のコピー
x = x * 2; // コピーを変更——元の変数には影響しない
std::cout << "関数内のx: " << x << std::endl;
}
int main() {
int num = 5;
doubleValue(num);
std::cout << "main内のnum: " << num << std::endl; // まだ5
return 0;
}
出力:
TEXT
📖 参照専用
関数内のx: 10
main内のnum: 5
(2) 1.2 値渡しはいつ使う?
- 小さな型(
int、char、bool、double)——コピーは安価 - 元の値を変更したくない——安全で予測可能
- 単純な計算——複雑なデータ構造が絡まない
2. 参照渡し
(1) 2.1 参照渡しの仕組み
参照渡しでは、パラメータは引数のエイリアス(別名)になる。コピーは作成されない。
CPP
#include <iostream>
void doubleValue(int &x) { // xは引数のエイリアス
x = x * 2; // 元の変数を直接変更
}
int main() {
int num = 5;
doubleValue(num);
std::cout << "main内のnum: " << num << std::endl; // 10になる
return 0;
}
出力:
TEXT
📖 参照専用
main内のnum: 10
💡 ヒント:
&が参照パラメータを示す。呼び出し側では何も変わらない——doubleValue(num)のまま。
(2) 2.2 参照渡しはいつ使う?
- 大きなオブジェクト(
std::string、配列、構造体)——コピーを避けパフォーマンス向上 - 元の値を変更する必要がある——複数の値を「返す」
- 効率が重要——巨大データ構造を扱う
3. const参照
(1) 3.1 「読み取り専用」パラメータ
大きなオブジェクトを渡すが、変更はしたくない場合、const参照を使う。
CPP
#include <iostream>
#include <string>
void printString(const std::string &s) { // コピーなし、変更不可
std::cout << s << std::endl;
// s = "Hello"; // ❌ コンパイルエラー: constオブジェクトを変更できない
}
int main() {
std::string name = "Alice";
printString(name);
printString("Bob"); // 一時オブジェクトも可能
return 0;
}
(2) 3.2 const参照の利点
| 利点 | 説明 |
|---|---|
| 効率的 | コピーを作成しない |
| 安全 | 呼び出し元の値が変更されないことを保証 |
| 柔軟 | 一時オブジェクト(リテラル)も受け取れる |
4. デフォルト引数
(1) 4.1 基本構文
パラメータにデフォルト値を指定できる。引数を渡さなければ、デフォルトが使われる。
CPP
#include <iostream>
void greet(std::string name = "Guest", int times = 1) {
for (int i = 0; i < times; i++) {
std::cout << "Hello, " << name << "!" << std::endl;
}
}
int main() {
greet(); // Hello, Guest!
greet("Alice"); // Hello, Alice!
greet("Bob", 3); // Hello, Bob! x3
return 0;
}
(2) 4.2 デフォルト引数のルール
- 右から左へ —— デフォルト引数はパラメータリストの右端から始める
- 連続 —— 中抜けは不可
- プロトタイプでのみ指定 —— 定義ではなくプロトタイプでデフォルト値を書く
TEXT
📖 参照専用
void func(int a, int b = 2, int c = 3); // ✅ OK
void func(int a = 1, int b, int c = 3); // ❌ エラー: 中抜け
5. 複数の値を返す
C++の関数は1つの戻り値しか返せないが、参照パラメータを使えば複数の値を「返せる」。
▶ サンプル 1:複数の値を返す(難易度 ⭐⭐)
CPP
#include <iostream>
void calculateStats(int a, int b, int &sum, int &product, double &average) {
sum = a + b;
product = a * b;
average = (a + b) / 2.0;
}
int main() {
int x = 10, y = 3;
int sum, product;
double average;
calculateStats(x, y, sum, product, average);
std::cout << "和: " << sum << std::endl;
std::cout << "積: " << product << std::endl;
std::cout << "平均: " << average << std::endl;
return 0;
}
6. 値渡し vs 参照渡し
| 特徴 | 値渡し | 参照渡し |
|---|---|---|
| コピー | 作成する | 作成しない |
| 元の変数 | 変更されない | 変更できる |
| パフォーマンス | 小さな型では高速 | 大きな型では高速 |
| 安全性 | 安全(副作用なし) | 注意が必要 |
| 構文 | void f(int x) |
void f(int &x) |
▶ サンプル 2:デフォルト引数を使う(難易度 ⭐)
CPP
#include <iostream>
#include <string>
void greet(std::string name = "Guest", int times = 1) {
for (int i = 0; i < times; i++) {
std::cout << "Hello, " << name << "!" << std::endl;
}
}
int main() {
greet(); // Hello, Guest!
greet("Alice"); // Hello, Alice!
greet("Bob", 3); // Hello, Bob! x3
return 0;
}
▶ サンプル 3:const参照で文字列を処理(難易度 ⭐⭐)
CPP
#include <iostream>
#include <string>
int countVowels(const std::string& text) {
int count = 0;
for (char c : text) {
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
count++;
}
}
return count;
}
int main() {
std::string message = "Hello World";
std::cout << "母音の数: " << countVowels(message) << std::endl;
return 0;
}
❓ よくある質問
Q 配列は値渡しできる?
A いいえ!C++では配列はポインタとして減衰——配列をパラメータに渡すと、最初の要素へのポインタになる。配列を「値渡し」したい場合、構造体でラップするか
std::arrayを使う。Q const参照と値渡しのどちらを使うべき?
A 小さな型(
int、char、double)は値渡し——コピーは安価。大きな型(std::string、構造体)はconst参照——コピーを避ける。Q デフォルト引数を途中で省略できる?
A いいえ。デフォルト引数は右から左へ適用。
func(1, , 3)は無効。Q 参照パラメータは
nullptrになり得る?A いいえ。参照は有効なオブジェクトを指す必要がある。ポインタのような「参照先なし」は存在しない。
📖 まとめ
- 値渡しはコピーを作成——元の変数は安全
- 参照渡しはエイリアスを作成——元の変数を変更可能
- const参照は大きなオブジェクトを安全かつ効率的に渡す
- デフォルト引数はパラメータをオプションにする——右から左へ
- 参照パラメータを使って複数の値を返す
📝 練習問題
-
初級(難易度 ⭐): 文字列を大文字に変換する
void toUpper(std::string &s)関数を書く。 -
中級(難易度 ⭐⭐):
void getStats(const std::string &s, int &letters, int &digits, int &spaces)関数を書く。文字列内の文字、数字、スペースの数をカウント。 -
上級(難易度 ⭐⭐⭐): 数のリストから最小値、最大値、平均を計算する関数を書く。3つの値すべてを参照パラメータで返す。