一、结构体的基本概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
二、结构体定义和使用
语法: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会提示报错)。
戳戳小手帮忙点个免费的赞和关注吧,嘿嘿。 |