【C++】C8_结构、联合与枚举

0 引言

struct
union
enum
enum class

1 struct

type 特点
数组 相同类型元素的集合
结构体 任意类型元素的集合

默认情况下,比较运算符不适用于结构体,除非用户自己定义这些运算符

struct对象中,成员按照生命的顺序依次存放。注意字节对齐。
如果有空洞,最终计算的sizeof(),可能就不是简单的累加。

类型名字只要出现就能使用,eg.

struct Link {
     
	Link* prev;
	Link* succ;
};

但是只有声明全部完成后才能声明对象,eg.

struct No_good {
     
	No_good member; // 递归定义,无效
};

可以在真正定义一个struct类型之前使用其名字,只要中间不调用成员的名字和结构大小即可。

备注:C的结构体定义

typedef struct Name {
     
	// ...
} NameA;

2 struct vs class

struct是class的一种,与常见class不同的是,struct 成员默认是public
struct可以包含成员函数,比如,构造函数。
若仅按照默认的初始化顺序初始化结构体成员,不需要构造函数;反之,若需要改变实参的顺序、检验实参的有效性、修改实参或者建立不变式,则应编写专门的构造函数。

3 struct vs array

std::array是一种struct。

template<typename T, size_t N>
struct array {
      // 简化版本
	T elem[N];

	T* begin() noexcept {
     return elem;}
	const T* begin() const noexcept {
     return elem;}
	T* end() noexcept {
     return elem + N;}
	const T* end() const noexcept {
     return elem + N;}

	constexpr size_t size() noexcept;
	
	T& operator[](size_t n) {
     return elem[n];}
	const T& operator[](size_t n) const {
     return elem[n];}
	
	T* data() noexcept {
     return elem;}
	const T* data() const noexcept {
     return elem;}

	// ...
};

与内置数组相比,std::array的优势:
首先,std::array是一种真正的对象类型(可以进行赋值操作),其次,不会隐式地转换成指向元素的指针。

4 类型等价

对于两个struct,即使成员相同,仍是不同的类型。struct本身的类型与其成员不能混为一谈。

5 POD

plain old data
指能被“仅当作数据”处理的对象,程序员无需顾及类布局的复杂性以及用户自定义的构造、拷贝和移动语义。

POD对象:
不具有复杂的布局;
不具有非标准(用户自定义)的拷贝语义;
含有一个最普通的默认构造函数。

POD必须属于下列类型的对象:
标准布局类型;
平凡可拷贝类型;
具有平凡默认构造函数的类型

平凡类型trivial type:
一个平凡默认构造函数;
平凡拷贝和移动操作;

当一个默认构造函数无须执行任何实际操作时(若需定义一个默认构造函数,使用=default),则认为是平凡的。

一个类型具有非标准布局的条件:

  • 含有一个非标准布局的非static成员或基类;
  • 包含virtual函数;
  • 包含virtual基类;
  • 含有引用类型的成员;
  • 其中的非静态数据成员有多种访问修饰符;
  • 阻止了重要的布局优化:
    • 在多个基类中都含有非static数据成员,或者在派生类和基类中都含有非static数据成员
    • 基类类型与第一个非static数据成员的类型相同

标准布局类型是指与C的布局兼容的类型,并且能被常规的C++应用程序二进制接口(ABI)处理。

判断POD类型的方法

//  
// 标准库类型属性谓词
std::is_pod<T>::value

6 域

bit-field

struct PPN {
     
	uint PFN : 22;
	int : 3;
	uint CCA : 3;
	bool nonreachable : 1;
	bool dirty : 1;
	// ...
};

C++允许未命名的域。
域必须是整型或枚举类型。

注意:用域将几个变量打包在一个字节中并不一定能节省空间。虽然节省了数据空间,但是负责管理和操作这些变量的代码在绝大多数机器上都会更长。

7 联合体

特殊的struct

使用union的目的一般是使数据更紧密,但是实际上并没有提供多少。

尽可能少用union

8 union 与 class

可以使用一组派生类替代union,避免空间的浪费。

9 枚举

enum class 限定作用域的强类型枚举

枚举类型:基础类型,必须是一种带符号或无符号的整型,默认int

你可能感兴趣的:(C/C++,c++)