在C++11以后,很多基础语法都进行了修正。其中union
的行为向类对象进行了发展,在兼容原有语法定义的基础上进行了扩充:
union
可以拥有成员函数(包含构造函数和析构函数),但是不能有虚函数union
不能参与继承,不能成为基类也不能成为子类union
的成员对象不能为引用类型
对于全部成员都是build-in
的union
类,还可以向以往一样进行使用:
#include <iostream>
#include <cstdint>
union S
{
std::int32_t n; // 占用4字节
std::uint16_t s[2]; // 占用4字节
std::uint8_t c; // 占用1字节
}; // 整体占用4字节
int main()
{
S s = {0x12345678}; // 初始化第一个成员,当前s.n为活跃成员
// 于此点,读取 s.s 或 s.c 是未定义行为
std::cout << std::hex << "s.n = " << s.n << '\n';
s.s[0] = 0x0011; // s.s 现在是活跃成员
// 在此点,读取 s.n 或 s.c 是未定义行为
std::cout << "s.c is now " << +s.c << '\n' // 11 or 00, 依赖平台实现
<< "s.n is now " << s.n << '\n'; // 12340011 or 00115678
}
对于全部包含非built-in
的union
类,则:
- 如果非静态(non-static)成员带有非平凡的特殊(non-trivial special)成员函数(自定义的:复制/移动构造函数,复制/移动赋值函数,析构函数),则该
union
类的默认相关的复制/移动构造函数、复制/移动赋值函数、析构函数都会被删除,如果需要的话,要求用户自己定义实现,如果用户没有自己定义,则不能进行相关的复制/移动操作 - 如果非静态(non-static)成员带有非平凡的特殊(non-trivial special)构造函数(自定义的构造函数),则该
union
类的默认构造函数会被删除,如果需要的话,要求用户自己定义实现,如果用户没有自己定义,则不能该union
类不能进行实例化。 - 至多一个变体成员能拥有默认成员初始化值
- 不能有静态成员数据,但是可以有静态成员函数
- 全部成员的访问控制都是
public
第1、2点的意思是,如果成员数据类型是非平凡的(non-trivial),则union
类需要定义相关的构造函数、复制函数、移动构造、移动赋值函数、析构函数等。
union A {
int a;
double b;
std::string c;
A() : c("111") {} // 因为std::string拥有是非平凡的的数据类型,
~A() {} // 则A必须自定义构造函数和析构函数,否则无法进行实例化
// 如果想实现复制语义,还得自定义复制(构造)函数
};
第3点的意思是:
union A {
int a;
double b;
std::string c = "abc"; // 只有一个成员数据能拥有这种初始化值
~A(){};
};