结构体
什么是结构体
在C/C++中,结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。它可以把几种不同类型的数据项集合成结构体这样的单一类型。
”在 C 语言中,可以定义结构体类型,将多个相关的变量包装成为一个整体使用。在结构体中的变量,可以是相同、部分相同,或完全不同的数据类型。在 C 语言中,结构体不能包含函数。在面向对象的程序设计中,对象具有状态(属性)和行为,状态保存在成员变量中,行为通过成员方法(函数)来实现。C 语言中的结构体只能描述一个对象的状态,不能描述一个对象的行为。在 C++ 中,考虑到 C 语言到 C++ 语言过渡的连续性,对结构体进行了扩展,C++ 的结构体可以包含函数,这样,C++ 的结构体也具有类的功能,与class 不同的是,结构体包含的函数默认为 public,而不是 private。”——引用自“菜鸟教程”结构体变量和结构体类型的定义 | 菜鸟教程
本文所有案例代码:
结构体作用
“在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新的类型。
结构体在函数中的作用不是简便,其最主要的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。”
引用自“菜鸟教程”
如何创建结构体
语法:struct 结构体名 { 结构体成员列表 };
示例:
struct Student
{
string name;
int age;
};
结构变量的使用
结构是一个新的数据类型,因此结构变量也可以跟其它类型的变量一样赋值、运算,不同的是结构变量是以成员作为基本变量。
结构成员的表示方式为:结构变量.成员名
结构体声明一共有三种方式,既可以在结构体定义的时候进行声明,也可以像普通变量一样进行声明。
- struct 结构体 变量名
在C++中定义结构体变量时可以省略struct,但C不可以省略。所以以下示例中在声明变量时都省略了struct关键字。int main() { Student stu1; stu1.name="Miracle"; stu1.age=20; cout<<"学生:"<<stu1.name<<endl<<"年龄:"<<stu1.age<<endl; system("pause"); return 0; }
- struct 结构体名 变量名 = {成员1初始... }
Student stu2={"Miracle",20}; cout<<"学生:"<<stu2.name<<endl<<"年龄:"<<stu2.age<<endl; system("pause");
- 在定义结构体时,创建一个结构体变量。
struct Student { string name; int age; }s3;
int main() { s3.name="Miracle"; s3.age=20; cout<<"学生:"<<s3.name<<endl<<"年龄:"<<s3.age<<endl; system("pause"); return 0; }
完整示例:
#include <iostream>
#include "stdlib.h"
#include <string>
using namespace std;
struct Student
{
string name;
int age;
}s3;
int main()
{
Student stu1;
stu1.name="Miracle";
stu1.age=20;
cout<<"学生:"<<stu1.name<<endl<<"年龄:"<<stu1.age<<endl;
Student stu2={"Miracle",20};
cout<<"学生:"<<stu2.name<<endl<<"年龄:"<<stu2.age<<endl;
s3.name="Miracle";
s3.age=20;
cout<<"学生:"<<s3.name<<endl<<"年龄:"<<s3.age<<endl;
system("pause");
return 0;
}
如何初始化结构体
在C程序中,结构体成员在进行声明时是不能初始化的,比如下面的程序,在C程序中是不允许的。
struct Point
{
int x = 0;
int y = 0;
};
但是在C++中,C++11及以后是可以进行初始化的,以上代码是没有错误的。
结构体数组
结构体数组与基本类型数组概念一样,由于篇幅有限,本文不作多述。对于数组的概念,可以查阅文章C++语言基础入门(4) - 数组|序列
语法:struct 结构体名 数组名[元素个数] = { };
结构体定义
示例:
struct Student
{
string name;
int age;
};
结构体数组变量声明
struct Student students[2]={
{"M1",20},
{"M2",20}
};
int len=sizeof(students)/sizeof(students[0]);
for (int i = 0; i < len; i++)
{
cout<<"学生:"<<students[i].name<<" 年龄:"<<students[i].age<<endl;
}
结果 输出:
学生:M1 年龄:20
学生:M2 年龄:20
2022/11/2 11:00 有点累了,休息会,放空一下大脑。
结构体指针
结构指针是指向结构的指针。它由一个加在结构变量名前的* 操作符来定义, 例如用前面已说明的结构定义一个结构指针如下:
struct Student *student;
指针访问成员
使用结构指针对结构成员的访问,与结构变量对结构成员的访问在表达方式上有所不同。结构指针对结构成员的访问表示为:
结构指针名->结构成员
示例:
struct Student stu4={"Miracle",20};
struct Student *p=&stu4;
cout<<"学生:"<<p->name<<" 年龄:"<<p->age<<endl;
实际上,student->name 就是 (*student).name 的缩写形式,互相等价。
示例:
struct Student stu4={"Miracle",20};
struct Student *p=&stu4;
cout<<"学生:"<<p->name<<" 年龄:"<<p->age<<endl;
p->name="M4";
cout<<"学生:"<<p->name<<" 年龄:"<<p->age<<endl;
cout<<"学生:"<<(*p).name<<" 年龄:"<<(*p).age<<endl;
(*p).name="M5";
cout<<"学生:"<<p->name<<" 年龄:"<<p->age<<endl;
cout<<"学生:"<<(*p).name<<" 年龄:"<<(*p).age<<endl;
system("pause");
结果:
注意:需要指出的是结构指针是指向结构的一个指针,即结构中第一个成员的首地址,因此在使用之前应该对结构指针初始化,即分配整个结构长度的字节空间。
测试:
cout<<"Loc(stu.name):"<<&stu4.name<<endl;
cout<<"Loc(p):"<<p<<endl;
结果:
结构体的嵌套结构
嵌套结构是指在一个结构成员中可以包括其它一个结构
下面是一个有嵌套的结构的结构体定义
struct Address
{
string country="China";
string province;
string city;
string district;
string specificAddress;
};
struct Student
{
string name;
int age;
struct Address address;
};
如果要给 student 结构中成员 address 结构中的 province
赋值, 则可写成:student.address.province="FuJian";
结构体作参数
结构体参数与基本类型作参数可以说是如出一辙,并没有什么区别。也是分为值传递和引用传递。
见文章:
示例1:
void TestStructArg(Student stu)
{
cout<<"学生:"<<stu.name<<endl<<"年龄:"<<stu.age<<endl;
}
示例2:
void TestStructArg(struct Student stu)
{
cout<<"学生:"<<stu.name<<endl<<"年龄:"<<stu.age<<endl;
}
常量结构体
结构体作参数会发生值传递,会拷贝结构体下的所有成员,相比结构体指针来说,结构体值传递占用内存大。但若采用指针容易发生数据被修改。当我们一个函数仅需要读取结构体,不会对结构体数据作修改,那么有没有即安全又省内存的方法。有的,我们可以在结构体指针前标明const关键字,表面这个结构体指针是常量指针,指针指向的值不可修改。
关于常量指针,我有一篇文章很详细的介绍了,可以看C++语言入门-指针
示例:
cout<<"---------------------按下任意按键测试即安全又不会发生拷贝的结构体参数传递-------------------------"<<endl;
system("pause");
system("cls");
cout<<"----开始测试即安全又不会发生拷贝的结构体参数传递---"<<endl;
stu5.name="Jack";
TestStructArg(&stu5);
system("pause");
TestStructArg
方法定义
void TestStructArg(const Student *stu)
{
cout<<"学生:"<<stu->name<<endl<<"年龄:"<<(*stu).age<<endl;
}
输出:
----开始测试即安全又不会发生拷贝的结构体参数传递---
学生:Jack
年龄:20
请按任意键继续. . .