月ノ書

<C++>引数と戻り値

今回の記事でわかること
  • 関数に値を渡す「引数」の使い方が分かる
  • 関数から値を返す「戻り値」の使い方が分かる
  • 引数と戻り値を組み合わせて便利な関数が作れる

引数と戻り値とは

簡単に言うと「入力(引数)」と「出力(戻り値)」みたいなイメージ

基本のおさらい

関数は「入力(引数)を受け取る → 処理 → 結果(戻り値)を返す」箱みたいなものです
C++ の基本構文はこんな感じ

戻り値の型 関数名(引数リスト) {
    // 処理
    return 戻り値; // 戻り値がある場合
}

戻り値がないときは void を使います。引数がないときは空の括弧 () を書きます

関数を用いた実例

引数あり・戻り値なし

例:名前を受け取って挨拶を表示する関数

#include <iostream>
#include <string>
using namespace std;

void greet(string name) {
    cout << "こんにちは、" << name << "さん!" << endl;
}

int main() {
    greet("○○");
    greet("××");
    return 0;
}

/* 出力結果
こんにちは、○○さん!
こんにちは、××さん!
*/

引数なし・戻り値あり

例:乱数や定数を返す関数

#include <iostream>
using namespace std;

int getAnswer() {
    return 42;
}

int main() {
    int x = getAnswer();
    cout << "答えは " << x << " です" << endl;
    return 0;
}

/* 出力結果
答えは 42 です
*/

引数が不要でも、関数で処理を隠して結果だけ受け取れるのが便利

引数あり・戻り値あり(もっとも一般的)

例:2つの値を受け取って合計を返す

#include <iostream>
using namespace std;

int add(int a, int b) {
    return a + b;
}

int main() {
    cout << "5 + 7 = " << add(5, 7) << endl;
    return 0;
}

/* 出力結果
5 + 7 = 12
*/

呼び出し側は戻り値を変数で受け取ったり、そのまま式の中で使えます

複数の引数

例:3教科の平均値を返す関数

#include <iostream>
using namespace std;

double average(int a, int b, int c) {
    return (a + b + c) / 3.0;
}

int main() {
    cout << "平均点: " << average(70, 85, 90) << endl;
    return 0;
}

/* 出力結果
平均点: 81.6667
*/

引数はカンマで区切って複数渡せる。順番と型に注意

関数の応用

早期 return

無駄なネストを減らすテクニック。条件チェックして早く抜けると読みやすくなります

#include <iostream>
using namespace std;

int safeDivide(int a, int b) {
    if (b == 0) return 0; // エラー時は 0 を返す(簡易的)
    return a / b;
}

int main() {
    cout << safeDivide(10, 2) << endl;
    cout << safeDivide(10, 0) << endl; // 0 を返す
    return 0;
}

/* 出力結果
5
0
*/

注意:実務ではエラーを sentinel 値で返すか、例外を投げるか、std::optional を使うか設計を考える必要があります

引数の数が可変

可変長引数は C++ できるけど、初心者向けには std::vector や initializer_list を使う方法が分かりやすいです

#include <iostream>
#include <vector>
using namespace std;

double avgVec(const vector<int>& v) {
    if (v.empty()) return 0.0;
    int sum = 0;
    for (int x : v) sum += x;
    return (double)sum / v.size();
}

int main() {
    vector<int> v = {1,2,3,4};
    cout << avgVec(v) << endl;
    return 0;
}

/* 出力結果
2.5
*/

※ count や参照(&)は中級の話だけど、ここでは「可変長のデータを渡すなら vector を使う」で覚えておけばOK

複数の戻り値を返す方法

関数は基本1つの値を返しますが、std::pair / std::tuple / 構造体を使えば複数値を返せます。

例:配列の最小値と最大値を返す

#include <iostream>
#include <vector>
#include <utility> // pair
using namespace std;

pair<int,int> minMax(const vector<int>& v) {
    if (v.empty()) return {0,0};
    int mn = v[0], mx = v[0];
    for (int x : v) {
        if (x < mn) mn = x;
        if (x > mx) mx = x;
    }
    return {mn, mx};
}

int main() {
    vector<int> a = {4,9,1,7};
    auto res = minMax(a);
    cout << "min=" << res.first << ", max=" << res.second << endl;
    return 0;
}

/* 出力結果
min=1, max=9
*/

pair や struct に入れて返すと、戻り値をまとめて返せるので便利

配列を関数に渡すとき

C言語の配列と同じく、組み込み配列は関数に渡す問いにサイズ情報が消えやすいです。必ず長さを一緒に渡すか、std::vector を使うのが安全

include <iostream>
using namespace std;

void printArr(int arr[], int len) {
    for (int i = 0; i < len; ++i) cout << arr[i] << " ";
    cout << endl;
}

int main() {
    int a[] = {1,2,3};
    printArr(a, 3);
    return 0;
}

/* 出力結果
1 2 3
*/

なぜ関数を使うのか

初心者がよく言う「コード短いし main に全部書けば?」って思うのもわかりますが、関数を使う理由はちゃんとあります!

利点

わかりやすさの比較

// 間違いやすい:同じ処理を何度もコピペ
cout << "合計: " << (a + b + c) << endl;
cout << "合計: " << (x + y + z) << endl;

// 関数にまとめると分かりやすい
int sum3(int p, int q, int r) { return p + q + r; }
cout << "合計: " << sum3(a,b,c) << endl;
cout << "合計: " << sum3(x,y,z) << endl;

途中で引き算を入れたいとか、関数であれば1か所、コピペであればすべて修正する必要があるため、なるべく分けらる処理は関数で書くことをおすすめします

学習進捗

0
Would love your thoughts, please comment.x