C++ 结构体(struct):定义、用法与结构体数组
(从零基础到能写出常见场景,带完整示例 + 对比 + 常见坑)
结构体是 C++ 中非常重要的用户自定义复合类型,它让你能把不同类型的数据捆绑成一个整体,非常适合表示“实体”(学生、图书、坐标、员工等)。
1. struct 的基本定义方式(3 种常见写法)
| 写法 | 代码示例 | 特点 | 推荐场景 |
|---|---|---|---|
| 方式1:最规范、最常用 | “`cpp | ||
| 方式2:定义时顺便声明变量(C 风格遗留) | cpp<br>struct Student {<br> int id;<br> // ...<br>} stu1, stu2;<br> | 定义类型的同时创建变量 | 快速测试、小脚本 |
| 方式3:匿名结构体(极少用) | cpp<br>struct {<br> int x, y;<br>} point;<br> | 没有类型名,只能用一次 | 临时小结构 |
现代 C++ 推荐:方式1 + 使用 std::string 而不是 char[](更安全)。
2. 如何创建结构体变量 & 访问成员
#include <iostream>
#include <string>
struct Student {
int id;
std::string name;
char gender; // 'M' 或 'F'
int age;
double score;
};
int main() {
// 创建方式1:定义后声明
Student s1;
// 创建方式2:定义时初始化(最推荐)
Student s2 = {1001, "张三", 'M', 20, 88.5};
// C++11 统一初始化(推荐)
Student s3{1002, "李四", 'F', 19, 92.0};
// 访问成员:用 . 点运算符
s1.id = 1003;
s1.name = "王五";
s1.gender = 'M';
s1.age = 21;
s1.score = 76.5;
// 输出
std::cout << "学号:" << s1.id << "\n"
<< "姓名:" << s1.name << "\n"
<< "性别:" << s1.gender << "\n"
<< "年龄:" << s1.age << "\n"
<< "分数:" << s1.score << "\n";
return 0;
}
3. 结构体数组(超级常用!)
结构体数组 = 每个元素都是一个结构体,适合存储一批同类对象(比如一个班的所有学生)。
3.1 三种常见声明方式
// 方式1:固定大小(最常见)
Student class1[5]; // 5 个学生
// 方式2:初始化(C++11 统一初始化语法最清晰)
Student class2[4] = {
{1001, "小明", 'M', 20, 85.0},
{1002, "小红", 'F', 19, 92.5},
{1003, "小刚", 'M', 21, 78.0},
{1004, "小丽", 'F', 20, 88.5}
};
// 方式3:C++11 统一初始化(推荐,可省略部分成员,默认 0/空)
Student class3[3] {
{1005, "张伟"},
{}, // 全部默认初始化
{1007, "刘洋", 'M', 20, 90.0}
};
3.2 遍历 & 操作结构体数组(三种写法对比)
#include <iostream>
#include <string>
struct Student { /* 同上 */ };
int main() {
Student students[5] = {
{1001, "Alice", 'F', 20, 88.5},
{1002, "Bob", 'M', 21, 76.0},
{1003, "Carol", 'F', 19, 95.0},
{1004, "David", 'M', 20, 82.5},
{1005, "Eve", 'F', 22, 90.0}
};
// 写法1:普通 for 循环(最直观)
std::cout << "普通 for 循环:\n";
for(int i = 0; i < 5; i++) {
std::cout << students[i].id << "\t"
<< students[i].name << "\t"
<< students[i].score << "\n";
}
// 写法2:范围 for(C++11+,最现代、最推荐)
std::cout << "\n范围 for(只读):\n";
for(const auto& stu : students) { // const & 防止拷贝
std::cout << stu.id << "\t" << stu.name << "\t" << stu.score << "\n";
}
// 写法3:范围 for + 可修改
std::cout << "\n范围 for + 修改分数+5:\n";
for(auto& stu : students) {
stu.score += 5;
std::cout << stu.name << " 新分数:" << stu.score << "\n";
}
return 0;
}
4. 结构体数组 vs 普通数组 对比(为什么用 struct)
| 项目 | 普通数组(二维) | 结构体数组 | 优势说明 |
|---|---|---|---|
| 数据含义 | students[30][5] | Student stu[30] | 语义清晰(.name vs [1]) |
| 可读性 | 差(全是数字下标) | 好(.id .name .score) | 代码维护性大幅提升 |
| 类型安全 | 容易越界或错位 | 编译器检查成员类型 | 减少 bug |
| 扩展性 | 加一列要改所有代码 | 加成员只需改 struct 定义 | 后期维护友好 |
5. 常见坑 & 注意事项(面试/实际开发高频)
- 结构体大小 & 内存对齐
struct A { char c; int i; }; // 大小通常 8 字节(不是 5)
建议:把大成员放前面,或用 #pragma pack(1) 强制 1 字节对齐(但慎用)。
- 不要在结构体里放大数组
错:char buf[8192];(栈容易爆)
改:用std::string或std::vector<char> - 初始化顺序
C++11 前:必须按声明顺序初始化
C++11 后:支持指定成员初始化( designated initializers,C++20 更完善)
Student s{.id=1001, .name="Tom", .score=99.0}; // C++20
- 结构体数组传参
- 推荐:
void print(const Student arr[], int n)或void print(const std::vector<Student>& v) - 不推荐直接传大数组(栈开销大)
- C++ vs C 的 struct 区别
- C++ 的 struct 默认 public,可以有成员函数、构造函数
- 可以写:
cpp struct Point { int x, y; double distance() const { return std::sqrt(x*x + y*y); } };
6. 小练习(建议你敲一遍)
- 定义一个
struct Book {std::string title; std::string author; double price; int stock;}; - 创建包含 3 本书的结构体数组
- 写函数:找出最贵的书,并打印
- 写函数:把所有库存 < 5 的书价格打 8 折
希望这篇把 struct 和结构体数组的核心用法讲透了!
有哪部分还不太清楚?想看带成员函数的 struct、vector 版本、还是排序/查找示例?直接告诉我~ 😄