目录
结构体
结构体定义和使用
结构体数组
结构体指针
结构体嵌套结构体
结构体做函数的参数
结构体中const使用场景
结构体
结构体定义和使用
定义:
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。
语法:
struct 结构体名称
{
结构体成员列表
}; (struct 关键字不可省略)
创建结构体实例的三种方式: 推荐使用第一种、第二种。我个人喜欢使用第一种
① struct 结构体名 变量名;
eg: struct Student s1; (struct 关键字可省略)。
② struct 结构体名 变量名 = {成员值1,成员值2...}
eg: struct Student s2 ={ "李四",20, 95}; (struct 关键字可省略)。
③定义结构体时创建结构体变量
eg: struct Student{ string name;int age;int score;} s3;
成员访问方式:
结构体变量.属性名,点出来。
#include <iostream>
using namespace std;
// 结构体
// 需求:创建学生类型(姓名、年龄、成绩)的结构体
// 结构体定义(自定义的包含多种数据类型的类型集合)
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
int main()
{
    // 创建具体学生的三种方式
    // 第①种 习惯使用第一种 创建结构体时 struct关键字可以省略(定义结构体时不可以省略(代码第8行),定义变量时可以省略(代码第22、30、37行可省略struct关键字))
    struct Student s1;
    // s1属性赋值
    s1.age = 10;
    s1.name = "张三";
    s1.score = 100;
    cout << "姓名 :" << s1.name << "  年龄 :" << s1.age << "  成绩:" << s1.score << endl;
    // 第②种 struct Student s2={...}
    struct Student s2 =
        {
            "李四",
            20,
            95};
    cout << "姓名 :" << s2.name << "  年龄 :" << s2.age << "  成绩:" << s2.score << endl;
    // 第③种 在定义结构体时创建结构体变量 不推荐使用原因:定义时变给了实例 如果代码比较长或者看其他同事代码,有时忽然看到一个s3还要去找这个结构体在哪里定义的
    // struct Student
    // {
    //     // 姓名
    //     string name;
    //     // 年龄
    //     int age;
    //     // 成绩
    //     int score;
    // } s3;
    // s3.age = 30;
    // s3.name = "王五";
    // s3.score = 90;
    // cout << "姓名 :" << s3.name << "  年龄 :" << s3.age << "  成绩:" << s3.score << endl;
    return 0;
}
 
 
结构体数组
作用:
将自定义的结构体放入到数组中方便维护。
语法:
struct 结构体名 数组名[元素个数] = { {},{},...{}};
#include <iostream>
using namespace std;
// 结构体
// 结构体数组
// 需求:结构体定义->创建结构体数组->结构体数组赋值->遍历结构体数组
// ① 结构体定义
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
int main()
{
    // ② 创建结构体数组 ③ 结构体数组赋值 这里使用第二种方式直接定义时进行赋值。也可以定义完 stuArr[i].属性 进行逐一赋值(i为数组长度-1)
    struct Student stuArr[3] =
        {
            {"张三", 18, 100},
            {"李四", 20, 95},
            {"王五", 25, 90}};
            
    // ④ 遍历结构体数组
    for (int i = 0; i < sizeof(stuArr) / sizeof(stuArr[0]); i++)
    {
        cout << "姓名 :" << stuArr[i].name << "  年龄 :" << stuArr[i].age << "  成绩:" << stuArr[i].score << endl;
    }
    return 0;
}
 
 
结构体指针
作用:
通过指针访问结构体中成员。
利用操作符 ->可以通过结构体指针访问结构体属性。
#include <iostream>
using namespace std;
// 结构体
// 结构体指针
// 结构体定义
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
int main()
{
    // 创建学生结构体变量
    Student s1 = {"张三", 20, 100};
    // 通过指针指向结构体变量
    Student *p = &s1;
    // 通过指针访问结构体变量数据
    cout << "姓名 :" << p->name << "  年龄 :" << p->age << "  成绩:" << p->score << endl;
    return 0;
}
 
![]()
结构体嵌套结构体
作用:
结构体成员为结构体。
eg:老师与学生的关系。
#include <iostream>
using namespace std;
// 结构体
// 结构体嵌套结构体
// 学生结构体定义
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
// 老师结构体定义
struct Teacher
{
    // 职工编号
    int id;
    // 姓名
    string name;
    // 年龄
    int age;
    // 老师对应的学生
    struct Student stu;
};
int main()
{
    // 属性赋值两种方式
    // 第一种
    //  // 创建学生
    // Student s;
    // s.name = "张三";
    // s.age = 18;
    // s.score = 100;
    // // 创建老师
    // Teacher t;
    // t.name = "张老师";
    // t.age = 30;
    // t.id = 1;
    // t.stu = s;
    // 第二种
    Teacher t;
    t.name = "张老师";
    t.age = 30;
    t.id = 1;
    t.stu.name = "李四";
    t.stu.age = 20;
    t.stu.score = 98;
    // 通过指针访问结构体变量数据
    cout << "职工编号 :" << t.id << "   姓名:" << t.name << "  年龄:" << t.age
         << "   教的学生的姓名:" << t.stu.name << "   教的学生的年龄:" << t.stu.age << "   教的学生的分数:" << t.stu.score << endl;
    return 0;
}
 
 ![]()
结构体做函数的参数
作用:
将结构体作为参数向函数中传递。
传递方式:
- 值传递
 - 地址传递
 
#include <iostream>
using namespace std;
// 结构体
// 结构体做函数的参数
// 场景: 将学生作为参数传入,打印学生信息
// 学生结构体定义
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
// 打印学生信息
// 1. 值传递 当形参发生改变时传递的实参会不受到影响
void printStu(struct Student s)
{
    cout << "值传递"
         << "学生的姓名:" << s.name << "   学生的年龄:" << s.age << "   学生的分数:" << s.score << endl;
}
// 2. 地址传递 之前讲过 当形参发生改变时传递的实参会受到影响跟着改变
void printStu2(struct Student *s)
{
    cout << "地址传递"
         << "学生的姓名:" << s->name << "   学生的年龄:" << s->age << "   学生的分数:" << s->score << endl;
}
int main()
{
    // 创建结构体变量
    Student stu;
    stu.name = "张三";
    stu.age = 18;
    stu.score = 100;
    // 将学生作为参数传入
    // 1. 值传递
    printStu(stu);
    // 2. 地址传递
    printStu2(&stu);
    // 打印学生信息
    // cout<< "学生的姓名:" << stu.name << "   学生的年龄:" << stu.age << "   学生的分数:" << stu.score << endl;
    return 0;
}
 
 
这里面强调一下 :
- 值传递 当形参发生改变时传递的实参会不受到影响。
 - 地址传递 之前讲过 当形参发生改变时传递的实参会受到影响跟着改变。
 自行动手测试:
可以在打印里面对学生的属性进行部分修改,在main中验证实参是否受到影响。
结构体中const使用场景
作用:
用const防止误操作(只读)。
什么时候使用:
在参数进行值传递时,实际是进行了一次参数的拷贝,如果属性过多会造成内存溢出,所以我们通过地址传递可以节省内存空间,因为一个指针只占用四个字节,但是指针指向的是实参数据对应的内存地址,也就是同一块内存区域,这就存在我们前面所说的形参的改变影响到实参,有没有什么方法可以避免呢? 答案就是const,通过使用const修饰参数,参数变不可修改,否则编译报错。
#include <iostream>
using namespace std;
// 结构体
// 结构体中const使用场景
// 背景: 在参数进行值传递时,实际是进行了一次参数的拷贝,如果属性过多会造成内存溢出
// 所以我们通过地址传递可以节省内存空间,因为一个指针只占用四个字节,但是指针指向的是实参数据对应的内存地址,也就是同一块内存区域
// 这就存在我们前面所说的形参的改变影响到实参,有没有什么方法可以避免呢? 答案就是const
// 学生结构体定义
struct Student
{
    // 姓名
    string name;
    // 年龄
    int age;
    // 成绩
    int score;
};
// 2. 地址传递 之前讲过 当形参发生改变时传递的实参会受到影响跟着改变 现在通过const修饰,函数功能为只读时使用。
void printStu2(const Student *s)
{
    // s->age = 100; 编译报错 assignment of member 'Student::age' in read-only object s->age = 100;
    cout << "地址传递"
         << "学生的姓名:" << s->name << "   学生的年龄:" << s->age << "   学生的分数:" << s->score << endl;
}
int main()
{
    // 创建结构体变量
    Student stu;
    stu.name = "张三";
    stu.age = 18;
    stu.score = 100;
    // 将学生作为参数传入
    // 2. 地址传递
    printStu2(&stu);
    // 打印学生信息
    // cout<< "学生的姓名:" << stu.name << "   学生的年龄:" << stu.age << "   学生的分数:" << stu.score << endl;
    return 0;
}
 
 ![]()



















