11 非受限联合类型

非受限联合类型

11.1 联合类型在C++中的局限性

​ 过去C++标准规定,联合类型的成员变量类型不能是一个非平凡类型,即下面的代码不能通过编译:

union U
{
int x1;
float x2;
std::string x3; //存在自定义的构造函数
};

11.2 使用非受限联合类型

​ 在C++11中,允许联合类型的成员可以是除了引用以外的所有类型。如果联合类型中存在非平凡类型,则必须手动提供联合类型的构造和析构函数。

1. 一个可以但不好的例子

下面的代码可以被使用,但是联合类型在声明时一般不能确定使用哪个成员,因此应用场景较少。

例如:

#include <iostream>
#include <string>
#include <vector>

union U
{
U() :x3() {} //存在非平凡类型,必须手动提供构造函数
~U() { x3.~basic_string(); } //存在非平凡类型,必须手动提供析构函数
int x1;
float x2;
std::string x3;
std::vector<int> x4;
};

int main()
{
U u;
u.x3 = "hello world"; //使用的是x3成员
std::cout << u.x3;
}
2. 一个更常见的例子

下面的例子使用了placement new的技巧(在某个确定的空间直接构造,此前内存是存在的)来初始化构造成员:

#include <iostream>
#include <string>
#include <vector>

union U
{
U() {} //存在非平凡类型,必须手动提供构造函数
~U() {} //存在非平凡类型,必须手动提供析构函数
int x1;
float x2;
std::string x3;
std::vector<int> x4;
};

int main()
{
U u;
new(&u.x3) std::string("hello world");
std::cout << u.x3 << std::endl;
u.x3.~basic_string();

new(&u.x4) std::vector<int>;
u.x4.push_back(58);
std::cout << u.x4[0] << std::endl;
u.x4.~vector();

return 0;
}

3. 非受限联合类型对静态变量的支持

与类基本一致

#include <iostream>

union U
{
static int x1;
}
int U::x1 = 42;

int main()
{
std::cout << U::x1 << std::endl;
}