【C++核心】结构体、共用体详解

简介: 这篇文章详细讲解了C++中结构体和共用体的概念、定义、使用场景和案例,包括结构体的创建、数组、指针、嵌套、函数参数传递,以及共用体的特点和应用实例。

一. 结构体

1.1 结构体基本概念

结构体属于用户自定义的数据类型,允许用户存储不同的数据类型

1.2 结构体定义和使用

语法: struct 结构体名 { 结构体成员列表 };

通过结构体创建变量的方式有三种:

  • struct 结构体名 变量名
  • struct 结构体名 变量名 = { 成员1值 , 成员2值…}
  • 定义结构体时顺便创建变量

示例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
}stu3; //结构体变量创建方式3 


int main() {
   

    //结构体变量创建方式1
    struct student stu1; //struct 关键字可以省略

    stu1.name = "张三";
    stu1.age = 18;
    stu1.score = 100;
    cout << "姓名:" << stu1.name << " 年龄:" << stu1.age  << " 分数:" << stu1.score << endl;

    //结构体变量创建方式2
    struct student stu2 = {
    "李四",19,60 };
    cout << "姓名:" << stu2.name << " 年龄:" << stu2.age  << " 分数:" << stu2.score << endl;

    stu3.name = "王五";
    stu3.age = 18;
    stu3.score = 80;
    cout << "姓名:" << stu3.name << " 年龄:" << stu3.age  << " 分数:" << stu3.score << endl;

    return 0;
}

总结1:定义结构体时的关键字是struct,不可省略
总结2:创建结构体变量时,关键字struct可以省略
总结3:结构体变量利用操作符 ‘’.‘’ 访问成员

1.3 结构体数组

作用: 将自定义的结构体放入到数组中方便维护

语法: struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }

示例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
}

int main() {
   

    //结构体数组
    struct student arr[3]=
    {
   
        {
   "张三",18,80 },
        {
   "李四",19,60 },
        {
   "王五",20,70 }
    };

    for (int i = 0; i < 3; i++)
    {
   
        cout << "姓名:" << arr[i].name << " 年龄:" << arr[i].age << " 分数:" << arr[i].score << endl;
    }

    system("pause");
    return 0;
}

1.4 结构体指针

作用: 通过指针访问结构体中的成员,利用操作符 -> 可以通过结构体指针访问结构体属性

示例:

#include<iostream>
#include<string>
using namespace std;

//结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};


int main() {
   

    struct student stu = {
    "张三",18,100, };

    struct student * p = &stu;

    p->score = 80; //指针通过 -> 操作符可以访问成员

    cout << "姓名:" << p->name << " 年龄:" << p->age << " 分数:" << p->score << endl;

    return 0;
}

总结:结构体指针可以通过 -> 操作符 来访问结构体中的成员

1.5 结构体嵌套结构体

作用: 结构体中的成员可以是另一个结构体

例如: 每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体

示例:

#include<iostream>
#include<string>

using namespace std;

//学生结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//教师结构体定义
struct teacher
{
   
    //成员列表
    int id; //职工编号
    string name;  //教师姓名
    int age;   //教师年龄
    struct student stu; //子结构体 学生
};


int main() {
   

    struct teacher t1;
    t1.id = 10000;
    t1.name = "老王";
    t1.age = 40;

    t1.stu.name = "张三";
    t1.stu.age = 18;
    t1.stu.score = 100;

    cout << "教师 职工编号: " << t1.id << " 姓名: " << t1.name << " 年龄: " << t1.age << endl;

    cout << "辅导学员 姓名: " << t1.stu.name << " 年龄:" << t1.stu.age << " 考试分数: " << t1.stu.score << endl;

    return 0;
}

总结: 在结构体中可以定义另一个结构体作为成员,用来解决实际问题

1.6 结构体做函数参数

作用: 将结构体作为参数向函数中传递

传递方式有两种:值传递地址传递

示例:

#include<iostream>
#include<string>

using namespace std;

//学生结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//值传递
void printStudent(student stu )
{
   
    stu.age = 28;
    cout << "子函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;
}

//地址传递
void printStudent2(student *stu)
{
   
    stu->age = 28;
    cout << "子函数中 姓名:" << stu->name << " 年龄: " << stu->age  << " 分数:" << stu->score << endl;
}

int main() {
   

    student stu = {
    "张三",18,100};
    //值传递
    printStudent(stu);
    cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age << " 分数:" << stu.score << endl;

    cout << endl;

    //地址传递
    printStudent2(&stu);
    cout << "主函数中 姓名:" << stu.name << " 年龄: " << stu.age  << " 分数:" << stu.score << endl;

    return 0;
}

总结:如果不想修改主函数中的数据,用值传递,反之用地址传递

1.7 结构体中 const使用场景

作用: 用const来防止误操作

示例:

#include<iostream>
#include<string>
using namespace std;

//学生结构体定义
struct student
{
   
    //成员列表
    string name;  //姓名
    int age;      //年龄
    int score;    //分数
};

//const使用场景
void printStudent(const student *stu) //加const防止函数体中的误操作
{
   
    //stu->age = 100; //操作失败,因为加了const修饰
    cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:" << stu->score << endl;

}

int main() {
   

    student stu = {
    "张三",18,100 };

    printStudent(&stu);

    return 0;
}

1.8 结构体案例

1.8.1 案例1

案例描述:

学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:

  • 设计学生和老师的结构体,其中在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员;
  • 学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
  • 最终打印出老师数据以及老师所带的学生数据。

示例:

#include<iostream>
#include<string>
#include<ctime>
using namespace std;

struct Student
{
   
    string name;
    int score;
};
struct Teacher
{
   
    string name;
    Student sArray[5];
};

void allocateSpace(Teacher tArray[] , int len)
{
   
    string tName = "教师";
    string sName = "学生";
    string nameSeed = "ABCDE";
    for (int i = 0; i < len; i++)
    {
   
        tArray[i].name = tName + nameSeed[i];

        for (int j = 0; j < 5; j++)
        {
   
            tArray[i].sArray[j].name = sName + nameSeed[j];
            tArray[i].sArray[j].score = rand() % 61 + 40;
        }
    }
}

void printTeachers(Teacher tArray[], int len)
{
   
    for (int i = 0; i < len; i++)
    {
   
        cout << tArray[i].name << endl;
        for (int j = 0; j < 5; j++)
        {
   
            cout << "\t姓名:" << tArray[i].sArray[j].name << " 分数:" << tArray[i].sArray[j].score << endl;
        }
    }
}

int main() {
   

    srand((unsigned int)time(NULL)); //随机数种子 头文件 #include <ctime>

    Teacher tArray[3]; //老师数组

    int len = sizeof(tArray) / sizeof(Teacher);

    allocateSpace(tArray, len); //创建数据

    printTeachers(tArray, len); //打印数据

    return 0;
}
1.8.2 案例2

案例描述:

设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。

通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。

五名英雄信息如下:

        {"刘备",23,"男"},
        {"关羽",22,"男"},
        {"张飞",20,"男"},
        {"赵云",21,"男"},
        {"貂蝉",19,"女"},

示例:

#include<iostream>
#include<string>
using namespace std;

//英雄结构体
struct hero
{
   
    string name;
    int age;
    string sex;
};
//冒泡排序
void bubbleSort(hero arr[] , int len)
{
   
    for (int i = 0; i < len - 1; i++)
    {
   
        for (int j = 0; j < len - 1 - i; j++)
        {
   
            if (arr[j].age > arr[j + 1].age)
            {
   
                hero temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
//打印数组
void printHeros(hero arr[], int len)
{
   
    for (int i = 0; i < len; i++)
    {
   
        cout << "姓名: " << arr[i].name << " 性别: " << arr[i].sex << " 年龄: " << arr[i].age << endl;
    }
}

int main() {
   

    struct hero arr[5] =
    {
   
        {
   "刘备",23,"男"},
        {
   "关羽",22,"男"},
        {
   "张飞",20,"男"},
        {
   "赵云",21,"男"},
        {
   "貂蝉",19,"女"},
    };

    int len = sizeof(arr) / sizeof(hero); //获取数组元素个数

    bubbleSort(arr, len); //排序

    printHeros(arr, len); //打印

    system("pause");
    return 0;
}

二. 共用体(union)

union即为联合,它是一种特殊的类。通过关键字union进行定义,一个union可以有多个数据成员。例如

union Token{
   
   char cval;
   int ival;
   double dval;
};

以上代码定义了一个名为Token的联合,该联合中包含了3个数据成员。

2.1 共用体的优点

共用体的优点如下:

1、分段使用
2、节省空间:对于有几个变量不会在某一段时刻同时出现,那么我们利用共用体,可以节省内存空间。
3、代替强类型转换。例如:在网络编程中,经常会用到传入一串数据,这些数据将会以参数的形式传递给不同的函数。因此可以用到共用体,让共用体里面全都是函数指针,在同一时刻指向不同的函数。因此来提高编程效率,以及节省空间。

2.2 union的局限性

union中的对象成员,不能有构造函数、析构函数、重载的复制赋值运算符;对象成员的对象成员也不能有,依此类推
union不能继承

2.3 union案例

使用union保存成绩信息,并输出

#include <iostream>
using namespace std;

class ExamInfo {
   

public:
    ExamInfo(string n, char g):name(n),mode(GRADE),grade(g){
   }
    ExamInfo(string n, bool p):name(n),mode(PASS),grade(p){
   }
    ExamInfo(string n, int p):name(n),mode(PERCENTAGE),grade(p){
   }

    void show();

private:
    string name;
    enum {
   GRADE, PASS, PERCENTAGE} mode;
    union {
   
        char grade;
        bool pass;
        int percent;
    };

};

void ExamInfo::show() {
   
    cout << name << ": ";

    switch(mode) {
   
        case GRADE: cout << grade;break;
        case PASS: cout << pass ? "PASS" : "FAIL";break;
        case PERCENTAGE: cout << percent;break;
    }

    cout << endl;
}

int main() {
   

    ExamInfo examInfo1("English", 'B');
    ExamInfo examInfo2("Calculus", true);
    ExamInfo examInfo3("C++ Programming", 85);

    examInfo1.show();       // English: B
    examInfo2.show();       // Calculus: 1
    examInfo3.show();       // C++ Programming: 85

    return 0;
}
相关文章
|
8天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
4天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2463 14
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
4天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1502 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19274 29
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18822 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17515 13
Apache Paimon V0.9最新进展
|
6天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
365 11
|
1月前
|
存储 人工智能 前端开发
AI 网关零代码解决 AI 幻觉问题
本文主要介绍了 AI Agent 的背景,概念,探讨了 AI Agent 网关插件的使用方法,效果以及实现原理。
18697 16
|
2天前
|
算法 Java
JAVA并发编程系列(8)CountDownLatch核心原理
面试中的编程题目“模拟拼团”,我们通过使用CountDownLatch来实现多线程条件下的拼团逻辑。此外,深入解析了CountDownLatch的核心原理及其内部实现机制,特别是`await()`方法的具体工作流程。通过详细分析源码与内部结构,帮助读者更好地理解并发编程的关键概念。
|
2天前
|
SQL 监控 druid
Druid连接池学习
Druid学习笔记,使用Druid进行密码加密。参考文档:https://github.com/alibaba/druid
195 82