構造体

[C++] 関数に引数として構造体を渡す方法

C++では、関数に構造体を引数として渡す方法は主に2つあります。

1つ目は「値渡し」で、構造体のコピーが関数に渡されます。

この場合、関数内での変更は元の構造体に影響を与えません。

2つ目は「参照渡し」で、構造体への参照を渡します。

この場合、関数内での変更が元の構造体に反映されます。

参照渡しを使う際にconstを付けると、関数内で構造体を変更できなくなり、安全性が向上します。

構造体を関数に渡す基本的な方法

C++では、構造体を関数に渡す方法はいくつかありますが、最も基本的な方法は「値渡し」です。

値渡しでは、構造体のコピーが作成され、関数内でそのコピーが使用されます。

これにより、元の構造体には影響を与えません。

以下に、構造体を値渡しで関数に渡す例を示します。

#include <iostream>
// 構造体の定義
struct Person {
    std::string name;  // 名前
    int age;          // 年齢
};
// 構造体を引数に取る関数
void printPerson(Person p) {
    std::cout << "名前: " << p.name << std::endl;  // 名前を出力
    std::cout << "年齢: " << p.age << "歳" << std::endl;  // 年齢を出力
}
int main() {
    Person person;  // Person構造体のインスタンスを作成
    person.name = "山田太郎";  // 名前を設定
    person.age = 30;  // 年齢を設定
    printPerson(person);  // 構造体を関数に渡す
    return 0;  // プログラムの終了
}
名前: 山田太郎
年齢: 30歳

この例では、Personという構造体を定義し、printPersonという関数にその構造体のインスタンスを渡しています。

関数内で構造体のメンバーにアクセスし、情報を出力しています。

値渡しのため、元のpersonには影響を与えません。

値渡しと参照渡しの違い

C++では、関数に引数を渡す際に「値渡し」と「参照渡し」の2つの方法があります。

それぞれの特徴と違いを理解することは、プログラムの効率や動作に大きな影響を与えます。

以下に、値渡しと参照渡しの違いを表にまとめました。

特徴値渡し参照渡し
引数のコピー引数のコピーが作成される引数の参照が渡される
メモリ使用量コピーのためメモリを多く使用コピーしないためメモリ効率が良い
元のデータへの影響元のデータは変更されない元のデータが変更される可能性がある
パフォーマンス大きな構造体の場合、遅くなる大きな構造体でも高速に処理可能

値渡しの例

値渡しでは、関数に渡す際に構造体のコピーが作成されます。

以下の例では、値渡しを使用して構造体を関数に渡しています。

#include <iostream>
struct Person {
    std::string name;
    int age;
};
void modifyPerson(Person p) {
    p.age += 1;  // 年齢を1歳増やす
}
int main() {
    Person person;
    person.name = "佐藤花子";
    person.age = 25;
    modifyPerson(person);  // 値渡しで関数に渡す
    std::cout << "年齢: " << person.age << "歳" << std::endl;  // 元の年齢を出力
    return 0;
}
年齢: 25歳

この例では、modifyPerson関数内で年齢を変更していますが、元のpersonの年齢は変更されていません。

参照渡しの例

参照渡しでは、元のデータへの参照が渡されるため、関数内での変更が元のデータに影響を与えます。

以下の例では、参照渡しを使用しています。

#include <iostream>
struct Person {
    std::string name;
    int age;
};
void modifyPerson(Person& p) {  // 参照渡し
    p.age += 1;  // 年齢を1歳増やす
}
int main() {
    Person person;
    person.name = "佐藤花子";
    person.age = 25;
    modifyPerson(person);  // 参照渡しで関数に渡す
    std::cout << "年齢: " << person.age << "歳" << std::endl;  // 変更後の年齢を出力
    return 0;
}
年齢: 26歳

この例では、modifyPerson関数内で年齢を変更すると、元のpersonの年齢も変更されます。

値渡しと参照渡しの違いを理解することで、プログラムの設計やパフォーマンスを最適化することができます。

constを使った安全な参照渡し

C++では、参照渡しを使用することで、関数内で元のデータを変更することができますが、時には元のデータを変更したくない場合もあります。

そのような場合に役立つのがconst修飾子です。

constを使うことで、参照渡しを行いながらも、元のデータを保護することができます。

以下に、constを使った安全な参照渡しの例を示します。

const参照渡しのメリット

  • データの保護: 元のデータを変更できないようにすることで、意図しない変更を防ぎます。
  • パフォーマンスの向上: 大きな構造体をコピーすることなく、効率的にデータを渡すことができます。

const参照渡しの例

以下の例では、constを使って構造体を参照渡ししています。

関数内で元のデータを変更することはできません。

#include <iostream>
struct Person {
    std::string name;
    int age;
};
// const参照渡しを使用する関数
void printPerson(const Person& p) {  // const修飾子を使用
    std::cout << "名前: " << p.name << std::endl;  // 名前を出力
    std::cout << "年齢: " << p.age << "歳" << std::endl;  // 年齢を出力
}
int main() {
    Person person;
    person.name = "鈴木一郎";
    person.age = 40;
    printPerson(person);  // const参照渡しで関数に渡す
    return 0;  // プログラムの終了
}
名前: 鈴木一郎
年齢: 40歳

この例では、printPerson関数がconst Person&型の引数を受け取ります。

これにより、関数内でpのメンバーを変更することはできず、元のpersonのデータは安全に保たれます。

constを使用することで、データの整合性を保ちながら、効率的に関数を設計することが可能です。

ポインタを使った構造体の渡し方

C++では、ポインタを使用して構造体を関数に渡すこともできます。

ポインタを使うことで、構造体のアドレスを渡し、関数内でそのデータを直接操作することが可能になります。

これにより、メモリの効率的な使用や、元のデータの変更が容易になります。

以下に、ポインタを使った構造体の渡し方の例を示します。

ポインタ渡しのメリット

  • メモリ効率: 構造体のコピーを作成する必要がないため、メモリの使用量が少なくなります。
  • データの変更: 関数内で元のデータを直接変更することができます。

ポインタを使った構造体の渡し方の例

以下の例では、ポインタを使って構造体を関数に渡し、元のデータを変更しています。

#include <iostream>
struct Person {
    std::string name;
    int age;
};
// ポインタを使った構造体の渡し方
void modifyPerson(Person* p) {  // ポインタを引数に取る
    p->age += 1;  // 年齢を1歳増やす
}
int main() {
    Person person;
    person.name = "田中太郎";
    person.age = 35;
    modifyPerson(&person);  // 構造体のアドレスを渡す
    std::cout << "年齢: " << person.age << "歳" << std::endl;  // 変更後の年齢を出力
    return 0;  // プログラムの終了
}
年齢: 36歳

この例では、modifyPerson関数がPerson*型の引数を受け取ります。

main関数内で&personを使って構造体のアドレスを渡すことで、関数内でp->ageを通じて元のpersonの年齢を直接変更しています。

ポインタを使用することで、構造体のデータを効率的に操作することができます。

構造体を戻り値として返す方法

C++では、関数から構造体を戻り値として返すことができます。

これにより、関数内で生成した構造体のデータを呼び出し元に返すことが可能になります。

構造体を戻り値として返す方法には、値渡しと参照渡しの2つのアプローチがありますが、一般的には値渡しがよく使われます。

以下に、構造体を戻り値として返す方法の例を示します。

構造体を戻り値として返すメリット

  • データのカプセル化: 関数内で生成したデータを外部に返すことで、データの管理が容易になります。
  • 柔軟性: 関数の戻り値として構造体を使用することで、複数の値を一度に返すことができます。

構造体を戻り値として返す例

以下の例では、構造体を戻り値として返す関数を定義しています。

#include <iostream>
struct Person {
    std::string name;
    int age;
};
// 構造体を戻り値として返す関数
Person createPerson(const std::string& name, int age) {
    Person p;  // Person構造体のインスタンスを作成
    p.name = name;  // 名前を設定
    p.age = age;    // 年齢を設定
    return p;  // 構造体を戻り値として返す
}
int main() {
    // createPerson関数を呼び出して構造体を取得
    Person person = createPerson("高橋健一", 28);  
    // 取得した構造体の情報を出力
    std::cout << "名前: " << person.name << std::endl;  
    std::cout << "年齢: " << person.age << "歳" << std::endl;  
    return 0;  // プログラムの終了
}
名前: 高橋健一
年齢: 28歳

この例では、createPerson関数がPerson構造体を生成し、そのインスタンスを戻り値として返しています。

main関数内でこの戻り値を受け取り、構造体のメンバーにアクセスして情報を出力しています。

構造体を戻り値として返すことで、関数の結果を簡単に利用することができます。

実践的な例:構造体を使った関数設計

C++では、構造体を使ってデータを整理し、関数を設計することで、より効率的で可読性の高いプログラムを作成できます。

ここでは、構造体を使った実践的な例として、学生の情報を管理するプログラムを示します。

このプログラムでは、学生の情報を格納する構造体を定義し、学生の情報を追加、表示、更新する関数を設計します。

学生情報を管理する構造体の定義

まず、学生の情報を格納するための構造体を定義します。

#include <iostream>
#include <vector>
struct Student {
    std::string name;  // 学生の名前
    int age;          // 学生の年齢
    float gpa;        // 学生のGPA
};

学生情報を追加する関数

次に、学生情報を追加する関数を定義します。

この関数は、学生の名前、年齢、GPAを引数として受け取り、新しい学生情報をベクターに追加します。

void addStudent(std::vector<Student>& students, const std::string& name, int age, float gpa) {
    Student newStudent;  // 新しいStudent構造体のインスタンスを作成
    newStudent.name = name;  // 名前を設定
    newStudent.age = age;    // 年齢を設定
    newStudent.gpa = gpa;    // GPAを設定
    students.push_back(newStudent);  // ベクターに追加
}

学生情報を表示する関数

次に、全ての学生情報を表示する関数を定義します。

この関数は、学生情報のベクターを引数として受け取り、各学生の情報を出力します。

void displayStudents(const std::vector<Student>& students) {
    for (const auto& student : students) {  // 各学生の情報をループで表示
        std::cout << "名前: " << student.name << ", 年齢: " << student.age << "歳, GPA: " << student.gpa << std::endl;
    }
}

メイン関数での実行

最後に、メイン関数でこれらの関数を使用して学生情報を管理します。

int main() {
    std::vector<Student> students;  // 学生情報を格納するベクター
    // 学生情報を追加
    addStudent(students, "佐藤花子", 20, 3.5);
    addStudent(students, "鈴木一郎", 22, 3.8);
    addStudent(students, "高橋健二", 21, 3.2);
    // 学生情報を表示
    std::cout << "学生情報一覧:" << std::endl;
    displayStudents(students);  // 学生情報を表示する関数を呼び出す
    return 0;  // プログラムの終了
}

このプログラムでは、Student構造体を使用して学生の情報を管理し、addStudent関数で新しい学生を追加し、displayStudents関数で全ての学生情報を表示しています。

#include <iostream>
#include <vector>
struct Student {
    std::string name; // 学生の名前
    int age;          // 学生の年齢
    float gpa;        // 学生のGPA
};

void addStudent(std::vector<Student>& students, const std::string& name,
                int age, float gpa) {
    Student newStudent; // 新しいStudent構造体のインスタンスを作成
    newStudent.name = name;         // 名前を設定
    newStudent.age = age;           // 年齢を設定
    newStudent.gpa = gpa;           // GPAを設定
    students.push_back(newStudent); // ベクターに追加
}

void displayStudents(const std::vector<Student>& students) {
    for (const auto& student : students) { // 各学生の情報をループで表示
        std::cout << "名前: " << student.name << ", 年齢: " << student.age
                  << "歳, GPA: " << student.gpa << std::endl;
    }
}

int main() {
    std::vector<Student> students; // 学生情報を格納するベクター
    // 学生情報を追加
    addStudent(students, "佐藤花子", 20, 3.5);
    addStudent(students, "鈴木一郎", 22, 3.8);
    addStudent(students, "高橋健二", 21, 3.2);
    // 学生情報を表示
    std::cout << "学生情報一覧:" << std::endl;
    displayStudents(students); // 学生情報を表示する関数を呼び出す
    return 0;                  // プログラムの終了
}
学生情報一覧:
名前: 佐藤花子, 年齢: 20歳, GPA: 3.5
名前: 鈴木一郎, 年齢: 22歳, GPA: 3.8
名前: 高橋健二, 年齢: 21歳, GPA: 3.2

構造体を使うことで、関連するデータを一つの単位として扱うことができ、プログラムの可読性と保守性が向上します。

まとめ

この記事では、C++における構造体の基本的な使い方から、関数に引数として渡す方法、戻り値として返す方法、さらにはポインタや参照を使った効率的なデータ管理について詳しく解説しました。

構造体を活用することで、関連するデータを一つの単位として扱うことができ、プログラムの可読性や保守性が向上します。

これを機に、構造体を用いたプログラミングを実践し、より効果的なコードを書くことに挑戦してみてください。

関連記事

Back to top button