笔记复习
1.结构体指针
结构体指针指的是指向结构体变量的指针
作用:通过指针访问结构体中的成员
相比于直接访问结构体变量,使用结构体指针访问结构体中的变量占用内存更少,效率更高,并且由于指针的特殊性质,结构体指针可以修改结构体中的实参。
定义语法:结构体名 * 指针名;
调用语法:指针名->属性名
代码示例如下:
#include<iostream>
using namespace std;
struct student {
string name;
int age;
int score;
};
int main() {
student s = {"张三",18,100 };
//int* p = &s;
//不能依旧跟前面一样使用int*类型的指针,因为student*类型的值不能用于初始化int*类型的实体
struct student* p = &s;//给指针p结构体变量s的地址相当于给p一个访问s里面属性的权限
//通过指针访问结构体变量中的数据
cout << "name:" << p->name << "age:" << p->age << "score:" << p->score << endl;
return 0;
}
2.结构体嵌套结构体
即结构体中的成员可以是另一个结构体的变量,将结构体的变量放在想要包含该结构体变量的结构体定义中即可
具体实例:每个老师辅导一个学员,在老师的结构体中记录一个学生的结构体
那么我们需要定义两个结构体,分别是老师和学生,这时候我们需要先定义学生结构体,因为在学生结构体中不记录老师结构体,而在老师结构体中记录了学生结构体,如果老师结构体先被定义那么编译器就认不出学生结构体,会报错
定义学生结构体
struct student {
string name;
int age;
int score;
};
定义老师结构体
struct teacher {
int id;
string name;
int age;
student stu;
//将原本放在main函数中的结构体变量定义放在teacher结构体定义中
//teacher 结构体中包含了一个名为 stu 的成员,这个成员是 student 类型的。
// //这意味着每个 teacher 对象都会包含一个 student 对象作为它的一个属性。
//即每个老师都带一位学生
};
那么在调用的时候,我们依旧使用点函数,先表明我们要调用teacher结构体变量的stu属性,再调用stu属性中的其他属性
main函数中的代码如下:
int main() {
teacher t;
t.id = 10000;
t.name = "老王";
t.age = 50;
t.stu.name = "小王";
t.stu.age = 20;
t.stu.score = 60;
cout << "老师姓名:" << t.name << "老师编号:" << t.id << "老师年龄:" << 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;
};
struct teacher {
int id;
string name;
int age;
student stu;
};
int main() {
teacher t;
t.id = 10000;
t.name = "老王";
t.age = 50;
t.stu.name = "小王";
t.stu.age = 20;
t.stu.score = 60;
cout << "老师姓名:" << t.name << "老师编号:" << t.id << "老师年龄:" << t.age
<< "学员姓名:" << t.stu.name << "学员年龄:" << t.stu.age << "学员成绩:" << t.stu.score << endl;
return 0;
}
3.结构体做函数参数
作用:将结构体作为参数向函数中传递
传递的方式有两种,分别是值传递标题二和地址传递
a.值传递
struct student {
string name;
int age;
int score;
};
void printstu1(student s) {//参数列表中写传入参数的类型student和名字s
cout << "子函数1中 name:" << s.name << "age:" << s.age << "score:" << s.score << endl;
}
b.地址传递
struct student {
string name;
int age;
int score;
};
void printstu2(student *p) {//参数列表中写student*指明指针的类型
cout << "子函数2中 name:" << p->name << "age:" << p->age << "score" << p->score << endl;
}
值传递和地址传递的区别是,1.地址传递速度更快 2.当我们在值传递函数中修改属性的值时,修改的只是形参的值,并不会修改实参的值,当我们在地址传递的函数中修改属性的值时,形参和实参的值都会被修改,例如:
#include<iostream>
#include<string>
using namespace std;
struct student {
string name;
int age;
int score;
};
//1.值传递
void printstu1(student s) {
s.age = 25;//仅改变形参
cout << "子函数1中 name:" << s.name << "age:" << s.age << "score:" << s.score << endl;
}
//2.地址传递
void printstu2(student *p) {
p->age = 100;//同时改变形参和实参
cout << "子函数2中 name:" << p->name << "age:" << p->age << "score" << p->score << endl;
}
int main() {
student s;
s.name = " 张三";
s.age = 20;
s.score = 85;
//结构体做函数参数
printstu1(s);
//结构体地址做函数参数
printstu2(&s);//函数接收的是地址,要在s前面加取址符
cout << "main函数中打印 name:" << s.name << "age:" << s.age << "score" << s.score << endl;
return 0;
}
总结:当我们想要改变main函数中的数据时,同地址传递,反之用值传递
4.const关键字在结构体中的使用
前面我们讲地址传递比值传递速度更快,但这会带来一个缺点,即地址传递会修改掉实参的值,那么这时候我们就可以const关键字来防止这种操作发生,原理就是前面学到的常量指针
具体使用实在函数参数列表中指针的前面加上const,使函数接收的是一个常量指针,即指针的指向可以修改,但指针指向的值无法修改的一个指针,代码示例如下:
#include<iostream>
#include<string>
using namespace std;
struct student {
string name;
int age;
int score;
};
void stu(const student *p) {
//函数接收的是一个常量指针,这样我们在函数体内部就无法修改指针指向的值
//加上const之后,一旦有修改的操作就会报错,因此当出现实参的值被修改时,可以通过该操作检查代码
cout << "name:" << p->name << "age:" << p->age << "score:" << p->score << endl;
};
int main() {
//创建结构体变量
student s = { "张三",15,70 };
//通过函数来打印结构体变量的信息
stu(&s);
return 0;
};