[C++] 结构体Struct类型和变量定义

简介: [C++] 结构体Struct类型和变量定义

一、结构体的基本概念

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

二、结构体定义和使用

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

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

1、创建学生数据j结构类型 : 学生包括(姓名, 年龄, 分数)

//自定义数据类型,一些类型集合组成的一个类型
//语法   struct 类型名称  {成员列表}
struct student
{
    //成员列表
    //姓名
    string name;
    //年龄
    int age;
    //分数
    int score;
}s3;

2、通过学生结构类型从创建具体学生

int main()
{
    //2.1 struct 结构体名 变量名
    (struct) student s1;
    //给s1属性赋值,通过.访问结构体变量中的属性
    s1.name = "张三";
    s1.age = 18;
    s1.score = 100; 
    cout<<"姓名:"<<s1.name<<"年龄:"<<s1.age<<"分数:"<<s1.score<<endl;
    //2.2 struct 结构体名 变量名 = {成员1值,成员2值}
    (struct) student s2 = {"李四", 19, 90};
    cout<<"姓名:"<<s2.name<<"年龄:"<<s2.age<<"分数:"<<s2.score<<endl;
    //2.3 定义结构体时顺便创建变量
    s3.name = "王五";
    s3.age = 20;
    s3.score = 70; 
    cout<<"姓名:"<<s3.name<<"年龄:"<<s3.age<<"分数:"<<s3.score<<endl;
}

也可以通过下面方式为学生结构体成员赋初值:

struct student
{   
    string name;
    int age;
    int score;
}stu = {"ZhangSan" , 18, 100};    //定义类型的同时 定义变量并初始化

struct student
{
    string name;
    int age;
    int score;
  student() :name("ZhangSan"), age(18),score(100)
  {
  }
};

三、结构体数组

1、定义结构体

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

2.、创建结构体数组并给结构体中的元素赋初值

int main()
{
    struct student stuArray[3] = 
    {
        {"张三", 19, 90},
        {"李四", 18, 100},
        {"王五", 20, 80},
      }    
}

3、遍历结构体数组

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

四、结构体指针

struct student
{  
    string name;
    int age;
    int score;
}stu= {"张三", 19, 90},*pStu ;   //定义类型的同时 定义变量和赋初始值   并定义指针
int main()
{
    pStu = &stu
    cout<<"姓名:"<<pStu->name<<"年龄:"<<pStu->age<<"分数:"<<pStu->score<<endl;
}

结构体指针的一般形式为:struct 结构名 *结构变量指针名

这里注意的是结构体指针变量需要先赋值之后才可以去使用。pStu = &stu 是正确的,但 pStu =&student 是错误的。

因为结构名和结构变量是两个不同的概念。结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。因此上面&Teacher这种写法是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就能更方便地访问结构变量的各个成员。

五、结构体嵌套结构体

定义学生结构体:

struct student
{  
    string name;
    int age;
    int score;
}

定义老师结构体:

//定义老师结构体
struct teacher
{  
    int id;
    string name;
    int age;
    student stu;
}

//访问老师中的结构体成员:

int main()
{
     teacher t;
     t.id = 10086;
     t.name = "老王";
     t.age = 50;
     t.stu.name = "小王";
     t.stu.age = 20;
     t.stu.score = 90;
     cout<<"老师编号:"<<t.id<<"老师姓名:"<<t.name<<"老师年龄:"<<t.age"老师学生姓名:"<<t.stu.name<<endl;
}

六、结构体做函数参数

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

传递方式有两种:

  • 值传递
  • 地址传递

定义学生结构体:

struct student
{  
    string name;
    int age;
    int score;
}

打印学生信息的子函数(值传递)

void printStudent1(student s)
{  
     s.age = 40;   //这里修改结构成员age 的值后,主函数调用该函数时,age 的值更新为40,但最终打印s1.age时,age 值不会改变。
     cout<<"姓名:"<<s.name<<"年龄:"<<s.age<<"分数:"<<s.score<<endl;
}

打印学生信息的子函数(地址传递)

void printStudent1(student * s)
{  
     s->age = 40;//这里修改结构成员age 的值后,主函数调用该函数和最终打印s1->age时,age的值都会更新为40.
     cout<<"姓名:"<<s->name<<"年龄:"<<s->age<<"分数:"<<s->score<<endl;
}

主函数调用子函数,打印学生信息的三种方式

int mian
{
     student s1;
     s1.name = "张三";
     s1.age = 18;
     s1.score = 100; 
     //法一:值传递
     printStudent1(s1);
     //法二:地址传递
     printStudent1(&s1);  
     //法三:直接打印,使用值传递时,这里不会改变;使用地址传递时,如果子函数中成员发生改变,这里也会相应改变
     cout<<"姓名:"<<s1.name<<"年龄:"<<s1.age<<"分数:"<<s1.score<<endl;   
}

值传递和地址传递的区别就是,使用值传递时,如果在子函数中对结构成员变量数值进行更改,不会更新结构成员的初始值,只会在调用该子函数的时候,更新结构成员的初始值。而地址传递在子函数中对结构成员变量数值进行更改,函数的初始值会相应更新。

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

七、结构体中const使用场景

作用:用const来防止误操作()

const 使用场景:

struct student
{  
    string name;
    int age;
    int score;
}stu = {"张三", 19, 90} ;

这里采用地址传递,将函数中的形参改为指针,这样可以减少内存,因为指针只占四个字节,而且不会像值传递那样,复制一个新的结构成员副本出来。

但是虽然使用地址传递可以不用将成员信息全部都复制一遍,减少内存,但是为了防止在子函数中修改成员变量的值,导致主函数中成员变量的值发生改变,这里可以加上const

void printStudents(const student *s)
{  
     //s->age = 35;  //加入const ,这时修改age的值就会报错,可以防止我们的误操作
     cout<<"姓名:"<<s->name<<"年龄:"<<s->age<<"分数:"<<s->score<<endl;
}

总结:const 的使用就是又想使用指针传递,又怕误操作修改了子函数中的结构成员参数值,导致主函数中的结构成员参数值发生改变,即结构成员初始值发生改变。所以加上了const ,保证子函数只读不写(写的时候s->age会提示报错)。

 


戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。


目录
相关文章
|
2天前
|
存储 编译器 程序员
C++类型参数化
【10月更文挑战第1天】在 C++ 中,模板是实现类型参数化的主要工具,用于编写能处理多种数据类型的代码。模板分为函数模板和类模板。函数模板以 `template` 关键字定义,允许使用任意类型参数 `T`,并在调用时自动推导具体类型。类模板则定义泛型类,如动态数组,可在实例化时指定具体类型。模板还支持特化,为特定类型提供定制实现。模板在编译时实例化,需放置在头文件中以确保编译器可见。
22 11
|
4天前
|
C++
HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具
HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具
|
2月前
|
存储 安全 C++
C++:指针引用普通变量适用场景
指针和引用都是C++提供的强大工具,它们在不同的场景下发挥着不可或缺的作用。了解两者的特点及适用场景,可以帮助开发者编写出更加高效、可读性更强的代码。在实际开发中,合理选择使用指针或引用是提高编程技巧的关键。
24 1
|
20天前
|
JavaScript 前端开发 Java
通过Gtest访问C++静态、私有、保护变量和方法
通过Gtest访问C++静态、私有、保护变量和方法
20 0
|
29天前
|
安全 程序员 C语言
C++(四)类型强转
本文详细介绍了C++中的四种类型强制转换:`static_cast`、`reinterpret_cast`、`const_cast`和`dynamic_cast`。每种转换都有其特定用途和适用场景,如`static_cast`用于相关类型间的显式转换,`reinterpret_cast`用于低层内存布局操作,`const_cast`用于添加或移除`const`限定符,而`dynamic_cast`则用于运行时的类型检查和转换。通过具体示例展示了如何正确使用这四种转换操作符,帮助开发者更好地理解和掌握C++中的类型转换机制。
|
2月前
|
C++
使用 QML 类型系统注册 C++ 类型
使用 QML 类型系统注册 C++ 类型
29 0
|
15天前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
60 30
|
4天前
|
并行计算 Unix Linux
超级好用的C++实用库之线程基类
超级好用的C++实用库之线程基类
12 4
|
4天前
|
C++ Windows
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
|
4天前
|
C++
2合1,整合C++类(Class)代码转换为MASM32代码的平台
2合1,整合C++类(Class)代码转换为MASM32代码的平台