【C++】関数に構造体を渡す3つの方法(値渡し、ポインタ渡し、参照渡し)

目次

はじめに

C++で、関数の中で構造体のデータを利用したい場合、どのようにしてそのデータを関数に渡せばよいでしょうか? C++には、主に3つの方法があり、それぞれにメリットとデメリットがあります。

  1. 値渡し (Pass by Value): 構造体のコピーを作成して渡す、最もシンプルな方法。
  2. ポインタ渡し (Pass by Pointer): 構造体のメモリアドレスを渡す、C言語由来の伝統的で効率的な方法。
  3. 参照渡し (Pass by Reference): 構造体の参照を渡す、C++で推奨される、安全で効率的な方法。

この記事では、これら3つの方法について、それぞれの仕組みと使い方、そして使い分けのポイントを解説します。


3つの渡し方のサンプルコード

このコードは、Product(商品)構造体を、3つの異なる渡し方をする関数にそれぞれ渡して、同じ結果を表示するものです。

完成コード

#include <iostream>
#include <string>

using namespace std;

struct Product {
    int id;
    string name;
};

// 1. 値渡し (Pass by Value)
void displayByValue(Product item) {
    cout << "ID: " << item.id << ", 商品名: " << item.name << " (値渡し)" << endl;
}

// 2. ポインタ渡し (Pass by Pointer)
void displayByPointer(const Product* p_item) {
    cout << "ID: " << p_item->id << ", 商品名: " << p_item->name << " (ポインタ渡し)" << endl;
}

// 3. 参照渡し (Pass by Reference)
void displayByReference(const Product& r_item) {
    cout << "ID: " << r_item.id << ", 商品名: " << r_item.name << " (参照渡し)" << endl;
}

int main() {
    Product myProduct = {101, "高機能マウス"};

    // 各関数を呼び出す
    displayByValue(myProduct);
    displayByPointer(&myProduct);
    displayByReference(myProduct);
    
    return 0;
}

1. 値渡し (Pass by Value)

// 宣言: void displayByValue(Product item);
// 呼出: displayByValue(myProduct);
  • 仕組み: 関数を呼び出す際に、構造体myProduct完全なコピーが作成され、それが関数の仮引数itemに渡されます。
  • メリット:
    • 仕組みがシンプルで分かりやすい。
    • 関数内で何をしても、元のmyProductには一切影響がありません
  • デメリット:
    • 構造体のサイズが大きい場合、**コピーのコスト(時間とメモリ)**が無視できなくなります。

2. ポインタ渡し (Pass by Pointer)

// 宣言: void displayByPointer(const Product* p_item);
// 呼出: displayByPointer(&myProduct);
  • 仕組み: 構造体そのものではなく、それが格納されているメモリアドレスだけを関数に渡します。
  • メリット:
    • 大きな構造体を渡す場合でも、アドレス(通常4バイトか8バイト)を渡すだけなので、非常に高速で効率的です。
  • デメリット:
    • 呼び出し側はアドレス演算子 & を、関数側はポインタ * とアロー演算子 -> を使う必要があり、構文が少し複雑になります。
    • ポインタが NULL である可能性(ヌルポインタ)を考慮する必要があります。

3. 参照渡し (Pass by Reference)

// 宣言: void displayByReference(const Product& r_item);
// 呼出: displayByReference(myProduct);
  • 仕組み: 内部的にはポインタと似ていますが、関数側では通常の変数と同じように扱える、C++の便利な機能です。
  • メリット:
    • ポインタ渡しと同様に、コピーが発生しないため非常に効率的です。
    • 呼び出し側も関数側も、値渡しとほぼ同じシンプルな構文で記述できます。
    • ヌルポインタのような心配がありません。
  • デメリット:
    • 参照渡しであることを意識しないと、関数内で意図せず元の値を変更してしまう可能性があります。(これを防ぐために、変更が不要な場合は const を付けるのが一般的です)

まとめ

関数に構造体を渡す3つの方法を解説しました。

方法効率構文のシンプルさ安全性C++での推奨度
値渡し△ (コピーが発生)◎ (最もシンプル)◎ (元の値は不変)△ (小さな構造体のみ)
ポインタ渡し◎ (高速)△ (構文が複雑)◯ (C言語との互換性)
参照渡し◎ (高速)◎ (シンプル)◎ (最も推奨)

結論として、現代のC++では、パフォーマンスと書きやすさのバランスが最も良い「参照渡し (const付き)」を第一の選択肢として考えるのがベストプラクティスです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次