11 结构体

11.1 结构体基本概念

C++ 中,我们可以使用数组来存储许多相同类型的数据。例如,当我们想要存储一个班 C++ 课程的成绩时,我们可以使用数组存储。

而数据并非总是相同类型的。例如,要存储一名同学的数据,我们需要存储他的学号、姓名、性别等数据,这些数据有整数(int),有字符串(string)等。这些 数据的类型不同,所以不可以用数组来存储

于是,我们需要允许用户定义一种新的数据类型,把属于同一事物的若干个相关数据构成一个整体,统一管理。这就是 结构体

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

11.2 结构体类型声明

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

注意:不要忘记分号!

例子:

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

通过上面的代码,我们就声明了一个 结构体类型 。这是一种数据类型,与我们之前见过的数据类型(int, double, bool...)一样,它可以用来定义变量。数据类型本身不占用内存,它的作用是告诉编译器,这个类型的变量应该怎样分配内存。

11.3 结构体类型变量的定义与初始化

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

  1. 先声明结构体类型,再定义变量;
struct student
{
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};
student stu1, stu2;
  1. 在声明结构体类型的同时,定义变量;
struct student
{
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
} stu1, stu2;
  1. 直接定义结构体类型变量。

这种方式声明的结构体类型没有类型名,不能再用来定义新变量。

struct
{
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
} stu1, stu2;

说明:

  1. 结构体变量的成员,也可以是结构体变量。
// “日期”结构体,包含年,月,日
struct date
{
	int year;
        int month;
        int day;
};

struct student
{
	string name;  //姓名
	date birthday;//生日
	int score;    //分数
};
  1. 结构体可以在定义时初始化。
struct student
{
	string name;  //姓名
	int age;      //年龄
	int score;    //分数
};
student stu1 = {"张三", 18, 100};
  1. 与数组类似,初始化时,如果不完全初始化,余下的成员变量均为 0 。

11.4 结构体变量的引用

11.4.1 结构体变量整体

结构体变量,不能以变量的形式整体进行赋值或运算。

  1. 结构体变量一般也不能直接整体使用。
student stu1;
cout << stu1 << endl;  // 错误
  1. 两个相同类型的结构体变量可以互相赋值。相对于为被赋值的结构体变量中的每一项成员变量赋右边的每一项成员变量的值,而不是地址复制。
student stu1, stu2;
stu1 = stu2;           // 正确

11.4.2 结构体变量成员

一般我们使用结构体变量,是通过使用它的各个成员变量实现的。

语法: 结构体变量名.成员名

. 为成员名运算符, 拥有最高优先级 ,指出了对该变量的操作对象。

示例:

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

int main() {
	struct student stu1; //struct 关键字可以省略

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

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

	return 0;
}

11.5 结构体数组

作用: 将结构体放入到数组中方便使用。使用方法与普通数组相同。

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

示例:

//结构体定义
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;
	}

	return 0;
}

11.6 结构体指针

作用: 通过指针访问结构体中的成员。

  • 利用操作符 -> 可以通过结构体指针访问结构体属性。本操作符的优先级与 . 相同,因此 ++p->id 等价于 ++(p->id)
  • 我们也可以使用 (* 指针名).成员名 来访问结构体成员。

示例:

//结构体定义
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;
}

11.7 拓展 · 共用体

共用体类型,十分类似于结构体,最大的区别在于: 共用体变量的所有成员将占用同一个存储空间

从这一点就可以看出,这种类型在同一时间只能使用其中一个成员,具有很大的局限性,基本上只用在存储空间十分有限的机器上。

声明:union 共用体名 { 成员列表 };