C++: C++ 構造体

最終更新:2026-08-31

配列は同じ型のデータをまとめますが、異なる型のデータ(名前(string)、年齢(int)、点数(double))をまとめて管理したい場合は?

構造体(struct) —— 異なる型の変数をまとめて新しい型として定義できます。


1. 構造体とは?

(1) 1.1 構造体の特徴

特徴 説明
異なる型をまとめる 名前、年齢、点数など異なる型を1つに
データをグループ化 関連するデータをまとめて管理
関連データを一括処理 年齢、点数、名前をまとめて扱える

構造体の利点:

  1. メンバーの型が自由
  2. メモリ効率(配列と同様)
  3. 「クラス」の基礎(クラスの簡易版)

(2) 1.2 なぜ構造体が必要?

構造体を使わない場合:

▶ サンプル 2:コード例(難易度 ⭐)

CPP
#include <iostream>
#include <string>

int main() {
    std::string name1 = "Alice";
    int age1 = 20;
    double score1 = 92.5;
    
    std::string name2 = "Bob";
    int age2 = 21;
    double score2 = 88.0;
    // ... 生徒が100人いたら 3 × 100 = 300個の変数が必要!
    
    return 0;
}
▶ 試してみよう

構造体を使う場合:

CPP
#include <iostream>
#include <string>

struct Student {
    std::string name;
    int age;
    double score;
};

int main() {
    Student s1 = {"Alice", 20, 92.5};
    Student s2 = {"Bob", 21, 88.0};
    // ... 変数が1人につき1つだけでOK!
    
    return 0;
}


2. 構造体の宣言と定義

(1) 2.1 構造体の宣言

構文:

TEXT 📖 参照専用
struct 構造体名 {
    型1 メンバー1;
    型2 メンバー2;
    ...
};

例:

CPP
#include <iostream>
#include <string>

// 学生構造体を宣言
struct Student {
    std::string name;
    int age;
    double score;
}; // ⚠️ 注意:セミコロンが必要!

int main() {
    // 使用例
    return 0;
}
💡 ヒント: 構造体の定義の最後にセミコロンを忘れないでください!忘れるとコンパイルエラーになります。



3. 構造体変数の作成と初期化

(1) 3.1 構造体変数の作成

CPP
Student s1; // Student型の変数s1を作成

(2) 3.2 構造体変数の初期化

方法1:順序で初期化

TEXT 📖 参照専用
Student s1 = {"Alice", 20, 92.5};

方法2:メンバー名で初期化(C++20以降)

TEXT 📖 参照専用
Student s1 = {.name = "Alice", .age = 20, .score = 92.5};

方法3:個別に代入

TEXT 📖 参照専用
Student s1;
s1.name = "Alice";
s1.age = 20;
s1.score = 92.5;
💡 ヒント: 方法1(順序で初期化)が最も簡潔です。



4. 構造体メンバーへのアクセス

(1) 4.1 メンバーへのアクセス

構文:

TEXT 📖 参照専用
変数名.メンバー名

例:

CPP
#include <iostream>
#include <string>

struct Student {
    std::string name;
    int age;
    double score;
};

int main() {
    Student s1 = {"Alice", 20, 92.5};
    
    std::cout << "名前:" << s1.name << std::endl; // Alice
    std::cout << "年齢:" << s1.age << std::endl; // 20
    std::cout << "点数:" << s1.score << std::endl; // 92.5
    
    return 0;
}

(2) 4.2 メンバーの変更

CPP
Student s1 = {"Alice", 20, 92.5};
s1.score = 95.0; // 点数を変更
std::cout << "新しい点数:" << s1.score << std::endl; // 95.0


5. 構造体を関数に渡す

(1) 5.1 値渡し

TEXT 📖 参照専用
void printStudent(Student s) { // ❌ 値渡し:コピーが発生
    std::cout << "名前:" << s.name << std::endl;
}

(2) 5.2 参照渡し

CPP
void printStudent(const Student& s) { // ✅ 参照渡し:コピーなし、変更不可
    std::cout << "名前:" << s.name << std::endl;
    std::cout << "年齢:" << s.age << std::endl;
    std::cout << "点数:" << s.score << std::endl;
}
💡 ヒント: 構造体を関数に渡す際は、const 参照を使いましょう —— コピーを避け、誤って変更することも防げます。



6. 構造体配列

構造体も配列にできます!

例:学生配列(難易度 ⭐⭐)

CPP
#include <iostream>
#include <string>

struct Student {
    std::string name;
    int age;
    double score;
};

int main() {
    Student students[3] = {
        {"Alice", 20, 92.5},
        {"Bob", 21, 88.0},
        {"Charlie", 19, 95.0}
    };
    
    // 全学生の情報を表示
    for (int i = 0; i < 3; i++) {
        std::cout << "========== 学生 " << i + 1 << " ==========" << std::endl;
        std::cout << "名前:" << students[i].name << std::endl;
        std::cout << "年齢:" << students[i].age << std::endl;
        std::cout << "点数:" << students[i].score << std::endl;
        std::cout << std::endl;
    }
    
    return 0;
}

出力:

TEXT 📖 参照専用
========== 学生 1 ==========
名前:Alice
年齢:20
点数:92.5

========== 学生 2 ==========
名前:Bob
年齢:21
点数:88.0

========== 学生 3 ==========
名前:Charlie
年齢:19
点数:95.0


7. 実践例:学生情報管理

▶ サンプル 1:簡易学生情報管理(難易度 ⭐⭐⭐)

CPP 📖 参照専用
#include <iostream>
#include <string>
#include <vector> // vectorを使用

struct Student {
    std::string name;
    int age;
    double score;
};

// 関数プロトタイプ
void addStudent(Student students[], int& count);
void printStudents(const Student students[], int count);
double calculateAverage(const Student students[], int count);

int main() {
    const int MAX_STUDENTS = 100;
    Student students[MAX_STUDENTS];
    int count = 0;
    
    int choice;
    do {
        std::cout << "========== 学生管理システム ==========" << std::endl;
        std::cout << "1. 学生追加" << std::endl;
        std::cout << "2. 学生一覧表示" << std::endl;
        std::cout << "3. 平均点数計算" << std::endl;
        std::cout << "4. 終了" << std::endl;
        std::cout << "選択してください(1-4):";
        std::cin >> choice;
        
        if (choice == 1) {
            addStudent(students, count);
        } else if (choice == 2) {
            printStudents(students, count);
        } else if (choice == 3) {
            if (count == 0) {
                std::cout << "学生がいません!" << std::endl;
            } else {
                std::cout << "平均点数:" << calculateAverage(students, count) << std::endl;
            }
        } else if (choice == 4) {
            std::cout << "終了します!" << std::endl;
        } else {
            std::cout << "無効な選択:1-4を入力してください!" << std::endl;
        }
        
        std::cout << std::endl;
        
    } while (choice != 4);
    
    return 0;
}

// 学生追加関数
void addStudent(Student students[], int& count) {
    if (count >= 100) {
        std::cout << "学生数が上限に達しました!" << std::endl;
        return;
    }
    
    std::cout << "名前を入力:";
    std::cin.ignore();
    std::getline(std::cin, students[count].name);
    
    std::cout << "年齢を入力:";
    std::cin >> students[count].age;
    
    std::cout << "点数を入力:";
    std::cin >> students[count].score;
    
    count++;
    std::cout << "学生を追加しました!" << std::endl;
}

void printStudents(const Student students[], int count) {
    if (count == 0) {
        std::cout << "学生がいません!" << std::endl;
        return;
    }
    
    std::cout << "\n========== 学生一覧 ==========" << std::endl;
    for (int i = 0; i < count; i++) {
        std::cout << i + 1 << ". 名前:" << students[i].name 
                  << "、年齢:" << students[i].age 
                  << "、点数:" << students[i].score << std::endl;
    }
    std::cout << "================================\n\n";
}

double calculateAverage(const Student students[], int count) {
    if (count == 0) {
        return 0.0;
    }
    
    double sum = 0.0;
    for (int i = 0; i < count; i++) {
        sum += students[i].score;
    }
    
    return sum / count;
}
論理コード 78 行(40 行制限超過、参照専用)

8. よくあるエラー

(1) 8.1 セミコロン忘れ

エラー例:

TEXT 📖 参照専用
struct Student { // ❌ セミコロン忘れ
    std::string name;
    int age;
} // ❌ ここにセミコロンがない

int main() {
    // ...
}

コンパイルエラー:

TEXT 📖 参照専用
error: expected ';' after struct definition

(2) 8.2 存在しないメンバーへのアクセス

エラー例:

CPP
struct Student {
    std::string name;
    int age;
};

int main() {
    Student s1;
    s1.score = 92.5; // ❌ エラー:Student には score がない
    return 0;
}

▶ サンプル 3:ネストした構造体(難易度 ⭐⭐)

CPP
#include <iostream>
#include <string>

struct Address {
    std::string city;
    std::string street;
};

struct Person {
    std::string name;
    int age;
    Address addr;  // ネストした構造体
};

int main() {
    Person p1;
    p1.name = "Alice";
    p1.age = 25;
    p1.addr.city = "Tokyo";
    p1.addr.street = "Shibuya";

    std::cout << p1.name << ", " << p1.age << " 歳" << std::endl;
    std::cout << "住所: " << p1.addr.street << ", " << p1.addr.city << std::endl;

    return 0;
}
▶ 試してみよう

出力:

TEXT 📖 参照専用
Alice, 25 歳
住所: Shibuya, Tokyo

❓ よくある質問

Q: 構造体とクラス(class)の違いは? A: 主な違いはデフォルトのアクセスレベルです:

  • struct のメンバーはデフォルトで public
  • class のメンバーはデフォルトで private

それ以外は、構造体もメンバー関数、コンストラクタなどを持てます。

Q: 構造体の中に構造体を入れられる? A: はい!構造体はネスト可能です。

CPP
struct Address {
    std::string city;
    std::string street;
};

struct Student {
    std::string name;
    Address addr; // 構造体をメンバーに
};

int main() {
    Student s1;
    s1.addr.city = "東京";
    s1.addr.street = "渋谷";
}

Q: 構造体変数のメモリサイズは? A: すべてのメンバーのサイズの和に、パディングが加わった値です(「メモリアライメント」による)。

CPP
struct Example {
    char c; // 1バイト
    int i; // 4バイト
};

std::cout << sizeof(Example) << std::endl; // 出力は8(1+4+パディング3バイト)

📖 まとめ


📝 練習問題

  1. 初級(難易度 ⭐): Book 構造体を定義し、タイトル、著者、価格のメンバーを持たせてください。Book 変数を作成し、値を設定して出力してください。

  2. 中級(難易度 ⭐⭐): Rectangle 構造体を定義し、幅と高さのメンバーを持たせてください。

    • 関数 double calculateArea(const Rectangle& r) を書く
    • 関数 double calculatePerimeter(const Rectangle& r) を書く
    • main 関数でテストする
  3. 上級(難易度 ⭐⭐⭐): Date 構造体を定義し(年、月、日)、日付の妥当性をチェックする関数を書いてください(例:2024-02-29はOK、2023-02-29はNG)。



9. 🚀 次のステップ

構造体を理解したら、次は フェーズ4(ポインタと参照) —— C++の核となる概念、メモリを直接操作する強力な機能を学ぼう!

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%