関数

[C++] 複数の戻り値を返す関数の定義方法

C++では、複数の戻り値を返す方法として以下の手法が一般的です。

1つ目はstd::tuplestd::pairを使用する方法で、複数の値をまとめて返します。

2つ目は参照引数を用いる方法で、関数の引数として渡した変数に結果を格納します。

3つ目は構造体やクラスを定義し、それを返す方法です。

これにより、可読性や拡張性が向上します。

std::pairを使った方法

C++の標準ライブラリには、2つの値をペアとして扱うことができるstd::pairというクラスがあります。

これを利用することで、簡単に複数の戻り値を返す関数を定義することができます。

以下にその方法を示します。

#include <iostream>
#include <utility> // std::pairを使用するために必要
// 2つの整数を受け取り、その和と積を返す関数
std::pair<int, int> calculate(int a, int b) {
    int sum = a + b; // 和を計算
    int product = a * b; // 積を計算
    return std::make_pair(sum, product); // std::pairで返す
}
int main() {
    int x = 5;
    int y = 3;
    
    // calculate関数を呼び出し、戻り値を受け取る
    std::pair<int, int> result = calculate(x, y);
    
    // 結果を表示
    std::cout << "和: " << result.first << std::endl; // 和を表示
    std::cout << "積: " << result.second << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

この例では、calculate関数が2つの整数を受け取り、その和と積をstd::pairとして返しています。

main関数内でこの戻り値を受け取り、firstメンバで和、secondメンバで積を表示しています。

std::pairを使うことで、簡潔に複数の戻り値を扱うことができます。

std::tupleを使った方法

C++の標準ライブラリには、任意の数の異なる型の値をまとめて扱うことができるstd::tupleというクラスがあります。

これを利用することで、複数の戻り値を返す関数をより柔軟に定義することができます。

以下にその方法を示します。

#include <iostream>
#include <tuple> // std::tupleを使用するために必要
// 3つの整数を受け取り、その和、差、積を返す関数
std::tuple<int, int, int> calculate(int a, int b, int c) {
    int sum = a + b + c; // 和を計算
    int difference = a - b - c; // 差を計算
    int product = a * b * c; // 積を計算
    return std::make_tuple(sum, difference, product); // std::tupleで返す
}
int main() {
    int x = 5;
    int y = 3;
    int z = 2;
    
    // calculate関数を呼び出し、戻り値を受け取る
    std::tuple<int, int, int> result = calculate(x, y, z);
    
    // 結果を表示
    std::cout << "和: " << std::get<0>(result) << std::endl; // 和を表示
    std::cout << "差: " << std::get<1>(result) << std::endl; // 差を表示
    std::cout << "積: " << std::get<2>(result) << std::endl; // 積を表示
    
    return 0;
}
和: 10
差: 0
積: 30

この例では、calculate関数が3つの整数を受け取り、その和、差、積をstd::tupleとして返しています。

main関数内でこの戻り値を受け取り、std::getを使って各メンバにアクセスし、結果を表示しています。

std::tupleを使うことで、異なる型の値をまとめて返すことができ、より多様な戻り値を扱うことが可能です。

参照引数を使った方法

C++では、参照引数を使用することで、関数から複数の値を返すことができます。

参照引数を使うと、関数の引数として渡した変数を直接変更することができるため、戻り値を使わずに複数の値を返すことが可能です。

以下にその方法を示します。

#include <iostream>
// 2つの整数を受け取り、その和と積を参照引数で返す関数
void calculate(int a, int b, int& sum, int& product) {
    sum = a + b; // 和を計算してsumに代入
    product = a * b; // 積を計算してproductに代入
}
int main() {
    int x = 5;
    int y = 3;
    int sum = 0; // 和を格納する変数
    int product = 0; // 積を格納する変数
    
    // calculate関数を呼び出し、参照引数で結果を受け取る
    calculate(x, y, sum, product);
    
    // 結果を表示
    std::cout << "和: " << sum << std::endl; // 和を表示
    std::cout << "積: " << product << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

この例では、calculate関数が2つの整数を受け取り、和と積を参照引数として受け取った変数に代入しています。

main関数内でこの関数を呼び出し、結果を表示しています。

参照引数を使うことで、戻り値を使わずに複数の値を返すことができ、コードがシンプルになります。

構造体やクラスを使った方法

C++では、構造体やクラスを使用して複数の戻り値を返すことができます。

これにより、関連するデータを一つのオブジェクトとしてまとめて扱うことができ、コードの可読性や保守性が向上します。

以下にその方法を示します。

構造体を使った例

#include <iostream>
// 和と積を格納するための構造体
struct Result {
    int sum; // 和
    int product; // 積
};
// 2つの整数を受け取り、その和と積を返す関数
Result calculate(int a, int b) {
    Result result; // Result構造体のインスタンスを作成
    result.sum = a + b; // 和を計算
    result.product = a * b; // 積を計算
    return result; // 構造体を返す
}
int main() {
    int x = 5;
    int y = 3;
    
    // calculate関数を呼び出し、戻り値を受け取る
    Result result = calculate(x, y);
    
    // 結果を表示
    std::cout << "和: " << result.sum << std::endl; // 和を表示
    std::cout << "積: " << result.product << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

クラスを使った例

#include <iostream>
// 和と積を計算するクラス
class Calculator {
public:
    int sum; // 和
    int product; // 積
    // 2つの整数を受け取り、和と積を計算するメソッド
    void calculate(int a, int b) {
        sum = a + b; // 和を計算
        product = a * b; // 積を計算
    }
};
int main() {
    int x = 5;
    int y = 3;
    
    Calculator calc; // Calculatorクラスのインスタンスを作成
    calc.calculate(x, y); // メソッドを呼び出して計算
    
    // 結果を表示
    std::cout << "和: " << calc.sum << std::endl; // 和を表示
    std::cout << "積: " << calc.product << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

この例では、構造体ResultとクラスCalculatorを使用して、和と積をまとめて返しています。

構造体やクラスを使うことで、関連するデータを一つのオブジェクトとして扱うことができ、コードの整理がしやすくなります。

C++17以降の機能を活用する方法

C++17以降では、複数の戻り値を返すための新しい機能や便利な機能が追加されました。

特に、構造化束縛(structured bindings)を使用することで、std::pairstd::tupleからの戻り値をより簡潔に扱うことができます。

以下にその方法を示します。

構造化束縛を使った例

#include <iostream>
#include <tuple> // std::tupleを使用するために必要
// 2つの整数を受け取り、その和と積を返す関数
std::tuple<int, int> calculate(int a, int b) {
    int sum = a + b; // 和を計算
    int product = a * b; // 積を計算
    return std::make_tuple(sum, product); // std::tupleで返す
}
int main() {
    int x = 5;
    int y = 3;
    
    // calculate関数を呼び出し、構造化束縛を使って戻り値を受け取る
    auto [sum, product] = calculate(x, y);
    
    // 結果を表示
    std::cout << "和: " << sum << std::endl; // 和を表示
    std::cout << "積: " << product << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

構造体のインライン初期化を使った例

C++17では、構造体のインライン初期化も可能になりました。

これにより、構造体のインスタンスを簡潔に作成できます。

以下にその例を示します。

#include <iostream>
// 和と積を格納するための構造体
struct Result {
    int sum; // 和
    int product; // 積
};
// 2つの整数を受け取り、その和と積を返す関数
Result calculate(int a, int b) {
    return {a + b, a * b}; // 構造体をインラインで初期化して返す
}
int main() {
    int x = 5;
    int y = 3;
    
    // calculate関数を呼び出し、戻り値を受け取る
    Result result = calculate(x, y);
    
    // 結果を表示
    std::cout << "和: " << result.sum << std::endl; // 和を表示
    std::cout << "積: " << result.product << std::endl; // 積を表示
    
    return 0;
}
和: 8
積: 15

C++17以降の機能を活用することで、複数の戻り値をより簡潔に扱うことができ、コードの可読性が向上します。

構造化束縛を使用することで、戻り値を直接変数に割り当てることができ、より直感的に値を扱うことが可能です。

実践的な使用例

複数の戻り値を返す関数は、さまざまな実践的なシナリオで役立ちます。

ここでは、実際のアプリケーションでの使用例をいくつか紹介します。

具体的には、データの処理や計算結果の取得など、実用的なケースを考えてみましょう。

1. 2D座標の計算

2D座標の計算を行う関数を作成し、和と距離を返す例です。

std::tupleを使用して、計算結果を返します。

#include <iostream>
#include <tuple>
#include <cmath> // sqrt関数を使用するために必要
// 2つの点の座標を受け取り、和と距離を返す関数
std::tuple<std::pair<int, int>, double> calculateCoordinates(int x1, int y1, int x2, int y2) {
    int sumX = x1 + x2; // x座標の和
    int sumY = y1 + y2; // y座標の和
    double distance = std::sqrt(std::pow(x2 - x1, 2) + std::pow(y2 - y1, 2)); // 距離を計算
    return {{sumX, sumY}, distance}; // 和と距離を返す
}
int main() {
    int x1 = 1, y1 = 2;
    int x2 = 4, y2 = 6;
    
    // calculateCoordinates関数を呼び出し、戻り値を受け取る
    auto [sumCoordinates, distance] = calculateCoordinates(x1, y1, x2, y2);
    
    // 結果を表示
    std::cout << "和の座標: (" << sumCoordinates.first << ", " << sumCoordinates.second << ")" << std::endl;
    std::cout << "距離: " << distance << std::endl;
    
    return 0;
}
和の座標: (5, 8)
距離: 5

2. 複数の統計値の計算

データセットから平均、最大、最小値を計算する関数を作成し、std::pairを使用して結果を返す例です。

#include <iostream>
#include <vector>
#include <algorithm> // std::max_element, std::min_elementを使用するために必要
// データセットを受け取り、平均、最大、最小を返す関数
std::tuple<double, int, int> calculateStatistics(const std::vector<int>& data) {
    double average = 0.0;
    int maxValue = *std::max_element(data.begin(), data.end()); // 最大値
    int minValue = *std::min_element(data.begin(), data.end()); // 最小値
    for (int value : data) {
        average += value; // 合計を計算
    }
    average /= data.size(); // 平均を計算
    return {average, maxValue, minValue}; // 統計値を返す
}
int main() {
    std::vector<int> data = {10, 20, 30, 40, 50};
    
    // calculateStatistics関数を呼び出し、戻り値を受け取る
    auto [average, maxValue, minValue] = calculateStatistics(data);
    
    // 結果を表示
    std::cout << "平均: " << average << std::endl;
    std::cout << "最大値: " << maxValue << std::endl;
    std::cout << "最小値: " << minValue << std::endl;
    
    return 0;
}
平均: 30
最大値: 50
最小値: 10

これらの実践的な使用例から、複数の戻り値を返す関数がどのように役立つかがわかります。

データの処理や計算結果の取得において、複数の値を効率的に返すことで、コードの可読性や保守性が向上します。

まとめ

この記事では、C++における複数の戻り値を返す方法について、さまざまなアプローチを紹介しました。

std::pairstd::tupleを利用する方法から、参照引数、構造体やクラスを使った方法、さらにはC++17以降の新機能を活用した例まで、多様な手法を通じて、実践的な使用例を交えながら解説しました。

これらの技術を活用することで、より効率的で可読性の高いコードを書くことが可能になりますので、ぜひ実際のプロジェクトに取り入れてみてください。

関連記事

Back to top button