C++篇:第七章_结构体、共用体和枚举_知识点大全
C++篇为本人学C++时所做笔记(特别是疑难杂点),全是硬货,虽然看着枯燥但会让你收益颇丰,可用作学习C++的一大利器
七、结构体、共用体和枚举
(一)结构体
-
C++的结构体中可以有构造函数,例:
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x),next(NULL) {} };
-
class中的成员默认都是private的,结构体中的成员默认都是public的
-
结构体类型是可以用户自定义和声明的,因此,结构体的类型应该是无数多种
4. 结构体变量的操作:
① 可以将一个结构体变量的值赋给另一个具有相同结构的结构体变量
② 只有结构变量的成员可以进行运算,变量之间不可以进行运算
③ 不能将一个结构体变量作为一个整体进行输入和输出,只能对结构体对象中的成员逐个进行输入或输出;例:student1和student2为结构体变量,并且它们已有值。不能cin>>student1;只能对结构体变量中的各个成员分别进行输入和输出
-
所有的成员在分配内存时都要与所有成员中占内存最多的数据类型所占内存空间的字节数对齐,例:最长的数据类型占 4 字节,所以是以 4 对齐
-
struct 能包含成员函数,能继承,能实现多态,可以有无参构造函数,和class的区别在于默认访问控制类型不同
-
struct成员类型不可以是它自己,因为会递归定义,理论上这样导致结构体的大小不能被计算(无限大小)。所以不能在结构体里的成员类型是结构体本身;但是成员可以定义为该结构体的指针
-
结构体对象可以进行赋值运算,但不能进行算术、关系运算等
-
将结构体对象作为函数实参传递到函数中,采用值传递的方法;将结构体数组和结构体指针作为函数参数,采用地址传递方式
10. 内存计算补齐原则:
数据对齐原则-内存按结构体成员的先后顺序排列,当排到该成员变量时,其前面所有成员已经占用的空间大小必须是该成员类型大小的整数倍,如果不够,则前面的成员占用的空间要补齐,使之成为当前成员类型的整数倍。假设是地址是从0开始,结构体中第一个成员类型char型占一个字节,则内存地址0-1,第二个成员从2开始,int型所占内存4个字节,根据原则b,第一个成员所占内存补齐4的倍数,故第一个成员所占内存:1 + 3 = 4; 第二个成员占5-8. 第三个成员占8个字节,满足原则b,不需要补齐,占9-16. 第四个成员占一个字节,占17. 故总内存为1 + 3 + 4 + 8 + 1 = 17个字节,但根据原则a,总字节数需是8的倍数,需将17补齐到24, 故此结构体总字节数为:24字节
-
结构体内什么数据类型占用内存最大,为n字节,则采用n字节对齐,例:
-
结构类型无法将自己的类型作为其成员的类型,因为自己的类型定义尚不完整,要在结束的大括号(})后才算定义完整
-
结构类型和其他基本类型或数组类型类似的用法,可以定义在函数之中或函数之外
14. 关于在结构体中用指针和用变长结构体(a[0])的区别:
① 在位置方面:指针可以放在任何地方,但是变长结构体的变长部分一定要放在结构体的最后。
② 在内存占用方面:指针会占一个指针的大小的内存空间,但是变长数组是不占内存的,它只是一个占位符。
③ 在内存布局方面:指针指向的内存和结构体的内存可以是不连续的,但是变长部分和结构体的内存必须是连续。
④ 在内存释放方面:使用指针,就要先释放指针所指的内存再释放整个结构体的内存,否则会照成内存泄露。
但是使用变长结构体直接释放整个结构体的空间就可以了
⑤ 一个限制:指针可以用在C++的类中,但是变长结构体就不可以了。因为有些编译器会将一些额外的信息放在类的最后,比如vptr或者虚基类的内容,使用了变长的类,就会把这部分的值改变,这种行为是未定义的,谁也不知道会发生什么
⑥ 故在结构体中定义变长数组,会出现编译器会认为这就是一个长度为0的数组,而且会支持对于长数组的越界访问的情况
(二)共用体
-
共用体(联合)是一种同一存储区域由不同类型变量共享的数据类型;结构体是用同一个名字引用的相关变量的集合
-
共用体的大小取内部最大的字节数
-
union 是一种特殊的类, C与C++中都可以使用
-
定义格式:union 共用体类型名{成员列表};// 共用体类型名与union一起作为类型名称
-
定义共用体对象时只能按一个成员给予初值
-
所有成员的值是相同的,区别是不同的类型决定了使用这个值的全部还是部分
(三)枚举
- 声明枚举变量三种方法:
① enum 枚举类型名 {命名枚举量列表(例:枚举标识符=整型常数)} 枚举对象名列表;
// 例:enum DIR {LEFT,UP} dir=LEFT;(dir为对象名)
② enum 枚举类型名 枚举对象名列表;
③ enum {命名枚举量列表} 枚举对象名列表;
-
枚举变量是全局变量的情况下, 枚举值的缺省值是0,不是枚举的第一个值。 其他情况,其值是不定的,而且不限定于所列出的枚举值;初始化的话就: {......}x=123;
-
命名枚举常量(大括号中的元素)是一个整形常量值,故是右值不是左值
-
weekday = weekday(2) // 其中weekday是枚举型,需要用此C++形式的强制类型转换才能赋值2
weekday = (weekday)2 // 此为C语言的强制类型转换
- 枚举变量的大小,即枚举类型所占内存的大小。由于枚举变量的赋值,一次只能存放枚举结构中的某个常数。所以枚举变量的大小,实质是常数所占内存空间的大小(常数为int类型,当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节)
- 枚举值默认从零开始并从先前的值开始向上计数
- 定义枚举类型的主要目的是:增加程序的可读性
- 如果某个枚举符的值均为非负,该枚举的表示范围就是[0:2k-1],2k是能使所有枚举符位于此范围内的最小的2的幂;如果存在负的枚举符值,则该枚举的取值范围就是[-2k:2k-1].这样就定义了一个最小的位段,其中能保存所有的枚举符值的常规2补码表示;例enum Number{one=1, two=2, four=4, eight=8};的取值范围是 0~15