C++: C++ 構造体
最終更新:2026-08-31
配列は同じ型のデータをまとめますが、異なる型のデータ(名前(string)、年齢(int)、点数(double))をまとめて管理したい場合は?
構造体(struct) —— 異なる型の変数をまとめて新しい型として定義できます。
1. 構造体とは?
(1) 1.1 構造体の特徴
| 特徴 | 説明 |
|---|---|
| 異なる型をまとめる | 名前、年齢、点数など異なる型を1つに |
| データをグループ化 | 関連するデータをまとめて管理 |
| 関連データを一括処理 | 年齢、点数、名前をまとめて扱える |
構造体の利点:
- メンバーの型が自由
- メモリ効率(配列と同様)
- 「クラス」の基礎(クラスの簡易版)
(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;
}
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のメンバーはデフォルトでpublicclassのメンバーはデフォルトでprivateそれ以外は、構造体もメンバー関数、コンストラクタなどを持てます。
Q: 構造体の中に構造体を入れられる? A: はい!構造体はネスト可能です。
CPPstruct 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: すべてのメンバーのサイズの和に、パディングが加わった値です(「メモリアライメント」による)。
CPPstruct Example { char c; // 1バイト int i; // 4バイト }; std::cout << sizeof(Example) << std::endl; // 出力は8(1+4+パディング3バイト)
📖 まとめ
- 構造体 は異なる型の変数をまとめて新しい型として定義
- 構文:
struct 構造体名 { メンバー一覧 };(セミコロン必須!) - 初期化:
構造体名 変数名 = {値1, 値2, ...}; - メンバーへのアクセス:
変数名.メンバー名 - 関数に渡す際は、
const参照を使用 - 構造体配列で複数のデータを管理
📝 練習問題
-
初級(難易度 ⭐):
Book構造体を定義し、タイトル、著者、価格のメンバーを持たせてください。Book変数を作成し、値を設定して出力してください。 -
中級(難易度 ⭐⭐):
Rectangle構造体を定義し、幅と高さのメンバーを持たせてください。- 関数
double calculateArea(const Rectangle& r)を書く - 関数
double calculatePerimeter(const Rectangle& r)を書く main関数でテストする
- 関数
-
上級(難易度 ⭐⭐⭐):
Date構造体を定義し(年、月、日)、日付の妥当性をチェックする関数を書いてください(例:2024-02-29はOK、2023-02-29はNG)。
9. 🚀 次のステップ
構造体を理解したら、次は フェーズ4(ポインタと参照) —— C++の核となる概念、メモリを直接操作する強力な機能を学ぼう!