C++学习笔记(5)union联合体

用法

声明联合体类型

联合体是一个特殊的类,他在同一时刻只能保持有一个非静态数据成员

语法

union attr class-head-name { member-specification }
  • class-head-name:所定义的联合体的名字。可以前附嵌套名说明符(名字与作用域解析运算符的序列,以作用域解析运算符::结尾)。可以忽略名字,此时联合体是无名 的
  • member-specification:访问说明符(access specifiers)、成员对象和成员函数的声明与定义的列表。
  1. 联合体可以拥有成员函数(包含构造函数和析构函数),但不能有虚函数。(必须是self closure)
  2. 联合体不能有基类且不能用作基类。
  3. 联合体不能拥有引用类型的非静态数据成员。(不能有别名,exclusive)
  4. 正如结构体的声明中一般,联合体的默认成员访问是 public。

解释

  1. 联合体的大小至少足以保有其最大的数据成员,但通常不会更大。
  2. 其他数据成员intend to分配于the same bytes as part of that largest member。
  3. 分配的细节由我们implementation-defined,但所有非静态数据成员均拥有相同的地址
  4. 读取并非最近written的联合体成员是undefined行为。
  5. 许多编译器以非标准语言扩展实现读取联合体的不活跃成员的能力。
union S
{
	std::int32_t n; // 4 bytes
	std::uint16_t s[2]; // 2*2=4 bytes
	std::uint8_t c; // 1 bytes
};

int main()
{
	S n={0x12345678}; //S.n is active member
	// 该时刻不能读S.s和S.c,因为这两个不是active member
	std::cout<<std::hex<<"s.n="<<s.n<<'\n';
	S.s[0]=0x0011; //S.s is active member
	// 该时刻不能读S.n和S.c了
	std::cout << "s.c is now " << +s.c << '\n' // 11 or 00, depending on platform
              << "s.n is now " << s.n << '\n'; // 12340011 or 00115678
}

在这里插入图片描述
每个成员在内存中的分配就好像他是class中的唯一成员一样

成员生存期

联合体成员的生存期从该成员被设为活跃时开始。如果之前已经有另一成员活跃,那么此前已有的这一成员生存期终止。

union A {int x; int y[4];};
struct B {A a;};
union C { B b; int k;};

int f()
{
	C c; // 不开始任何联合体成员的生存期
	c.b.a.y[3]=5; // 开始c.b和c.b.a.y成员生存期
	return c.b.a.y[3];
}

struct X { const int a; int b; };
union Y { X x; int k; };

void g()
{
	Y y={{1,2}}; // y.x is active union member
	int n=y.x.a;
	y.k=4; // ends lifetime of y.x
	y.x.b=n; // undefined behavior,因为y.x已经不存在了!
}
		

匿名联合体

匿名联合体有更多限制:

  • 不能有成员函数
  • 不能有静态数据成员
  • 所有数据成员必须公开。
int main()
{
	union
	{
		int a;
		const char* p;
	}
	a=1;
	p="Jennifer"
}

union-like classes

联合体式的类 是联合体,或是至少拥有一个匿名联合体成员的类。联合体式的类拥有一组变体成员(variant members):

  • 其成员匿名联合体中的非静态数据成员;
  • 如果联合体式的类是联合体,那么variant members是其并非匿名联合体的非静态数据成员。
struct S
{
	enum {CHAR, INT, DOUBLE} tag;
	union 
	{
		char c;
		int i;
		double d;
	};
};

void print_s(const S& s)
{
	switch(s.tag)
	{
		case S::CHAR: std::cout<<s.c<<std::endl; break;
		case S::INT: std::cout<<s.i<<std::endl; break;
		case S::DOUBLE: std::cout<<s.d<<std::endl; break;
	}
}

在这里插入图片描述

elaborated type specifier

若存在于作用域中的某个函数或变量所拥有的名字与某个联合体类型的名字相同,则可在该名字之前加上 union 以消歧义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值