C++: 结构体基础
最后更新:2026-08-26
数组能存多个同类型的数据,但如果要存一个学生的姓名(字符串)、年龄(整数)、成绩(浮点数)呢?
这就需要结构体——把多个不同类型的变量组合成一个整体。
1. 什么是结构体?
(1) 1.1 生活中的结构体
| 生活场景 | 程序中的对应 |
|---|---|
| 一张名片(姓名、电话、邮箱) | 结构体 |
| 一本书(书名、作者、价格) | 结构体 |
| 一个学生(姓名、年龄、成绩) | 结构体 |
结构体的特点:
- 成员类型可以不同
- 内存连续(和数组一样)
- 是"类"的前奏(后面会学类)
(2) 1.2 为什么需要结构体?
不用结构体(麻烦):
▶ 示例 2:代码示例(难度⭐)
#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;
// ... 要声明 3 × 100 个变量!
return 0;
}
输出:
(程序输出)
用结构体(简洁):
#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};
// ... 简洁多了!
return 0;
}
2. 结构体的声明与定义
(1) 2.1 声明结构体
语法:
struct StructName {
memberType1 memberName1;
memberType2 memberName2;
...
};
示例:
#include <iostream>
#include <string>
// 声明结构体
struct Student {
std::string name;
int age;
double score;
}; // ⚠️ 注意:分号不能少!
int main() {
// ...
return 0;
}
💡 重点: 结构体声明以分号结尾!这是新手常犯的错误。
3. 结构体变量的创建与初始化
(1) 3.1 创建结构体变量
Student s1; // 创建一个 Student 类型的变量 s1
(2) 3.2 初始化结构体变量
方法一:按声明顺序初始化
Student s1 = {"Alice", 20, 92.5};
方法二:指定成员初始化(C++20,推荐)
Student s1 = {.name = "Alice", .age = 20, .score = 92.5};
方法三:逐个赋值
Student s1;
s1.name = "Alice";
s1.age = 20;
s1.score = 92.5;
💡 提示: 推荐用方法一或方法二,更简洁。
4. 访问结构体成员
(1) 4.1 读取成员
语法:
structName.memberName
示例:
#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 修改成员
Student s1 = {"Alice", 20, 92.5};
s1.score = 95.0; // 修改成绩
std::cout << "新成绩:" << s1.score << std::endl; // 95.0
5. 结构体作为参数传递
(1) 5.1 传值(不推荐)
void printStudent(Student s) { // ❌ 传值:复制整个结构体,开销大
std::cout << "姓名:" << s.name << std::endl;
}
(2) 5.2 传引用(推荐)
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. 结构体数组
结构体也可以组成数组!
示例:学生数组(难度⭐⭐)
#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;
}
7. 实战:学生成绩管理(结构体版)
▶ 示例 1:完整的学生成绩管理(难度⭐⭐⭐)
#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;
}
输出:
========== 学生成绩管理 ==========
1. 添加学生
2. 显示所有学生
3. 计算平均分
4. 退出
请选择(1-4):
没有学生数据!
平均分:
再见!
错误:请输入 1-4 之间的数字!
学生数量已达上限!
请输入姓名:
请输入年龄:
请输入成绩:
添加成功!
没有学生数据!
========== 学生列表 ==========
. 姓名:
================================
▶ 示例 3:结构体作为函数返回值(难度⭐)
#include <iostream>
#include <string>
struct Student {
std::string name;
int age;
double score;
};
// 返回结构体的函数
Student createStudent(std::string n, int a, double s) {
Student stu;
stu.name = n;
stu.age = a;
stu.score = s;
return stu;
}
int main() {
Student s1 = createStudent("张三", 20, 92.5);
std::cout << "姓名:" << s1.name << std::endl;
std::cout << "年龄:" << s1.age << std::endl;
std::cout << "成绩:" << s1.score << std::endl;
return 0;
}
输出:
姓名:
年龄:
成绩:
8. 常见错误
(1) 8.1 忘记写分号
错误示例:
struct Student { // ❌ 忘记写分号
std::string name;
int age;
} // ❌ 这里应该有分号
int main() {
// ...
}
编译错误信息:
error: expected ';' after struct definition
(2) 8.2 访问不存在的成员
错误示例:
struct Student {
std::string name;
int age;
};
int main() {
Student s1;
s1.score = 92.5; // ❌ 错误:Student 没有 score 成员
return 0;
}
❓ 常见问题
struct 的默认访问权限是 public(公有) > - class 的默认访问权限是 private(私有)Q:关于structs basics最重要的是什么? A:先理解核心概念,再通过实践例子来巩固。
📖 小节
- 结构体把多个不同类型的变量组合成一个整体
- 声明结构体:
struct 结构体名 { 成员列表 };(注意分号!) - 初始化:
结构体名 变量名 = {值1, 值2, ...}; - 访问成员:
变量名.成员名 - 作为参数时,优先用
const引用 - 结构体也可以组成数组
📝 作业
-
基础题 (Difficulty ⭐): 定义一个
Book结构体,包含书名、作者、价格三个成员。创建两个Book变量并输出。 -
进阶题 (Difficulty ⭐⭐): 定义一个
Rectangle结构体,包含宽度和高度两个成员。 -
写一个函数
double calculateArea(const Rectangle& r)计算面积 -
写一个函数
double calculatePerimeter(const Rectangle& r)计算周长 -
在
main里测试 -
挑战题 (Difficulty ⭐⭐⭐): 定义一个
Date结构体(年、月、日),写一个函数判断一个日期是否合法(如 2024-02-29 合法,2023-02-29 不合法)。
- 结构体 struct:将不同类型数据打包成一个整体
- 成员访问用 . 运算符,指针用 ->
- 初始化:统一初始化 {} 或成员逐一赋值
- 结构体可作为函数参数和返回值
- 结构体数组管理多条记录
9. 🚀 下一步
学会了结构体,接下来我们进入 Phase 4(指针与引用)——这是 C++ 最核心也最难的部分,但掌握后能写出更高效的代码!