Union declaration
联合声明
联合是一种特殊的类类型,只能容纳它的非静态类之一。数据成员一次。
联合声明的类说明符类似于类或结构声明:
union attr class-head-name { member-specification } | | |
---|
attr(C++11) | - | optional sequence of any number of attributes |
---|---|---|
class-head-name | - | the name of the union that's being defined. Optionally prepended by nested-name-specifier (sequence of names and scope-resolution operators, ending with scope-resolution operator). The name may be omitted, in which case the union is unnamed |
member-specification | - | list of access specifiers, member object and member function declarations and definitions. |
联合可以有成员函数%28,包括构造函数和析构函数%29,但不具有虚拟函数。
联合不能有基类,也不能用作基类。
联合不能有引用类型的数据成员。
Unions cannot contain a non-static data member with a non-trivial special member function (copy constructor, copy-assignment operator, or destructor). | (until C++11) |
---|---|
If a union contains a non-static data member with a non-trivial copy/move constructor, copy/move assignment, or destructor), that function is deleted by default in the union and needs to be defined explicitly by the programmer. If a union contains a non-static data member with a non-trivial default constructor, the default constructor of the union is deleted by default unless a variant member of the union has a default member initializer. At most one variant member can have a default member initializer. | (since C++11) |
就像在结构声明中,联合中的默认成员访问权限为公众...
解释
工会的规模仅限于其最大的数据成员。其他数据成员作为该最大成员的一部分以相同的字节分配。该分配的详细信息是实现定义的,它是从最近编写的%27T的工会成员中读取的%27s未定义的行为。许多编译器实现,作为一个非标准的语言扩展,阅读一个联盟的不活跃成员的能力。
二次
#include <iostream>
union S
{
std::int32_t n; // occupies 4 bytes
std::uint16_t s[2]; // occupies 4 bytes
std::uint8_t c; // occupies 1 byte
}; // the whole union occupies 4 bytes
int main()
{
S s = {0x12345678}; // initializes the first member, s.n is now the active member
// at this point, reading from s.s or s.c is undefined behavior
std::cout << std::hex << "s.n = " << s.n << '\n';
s.s[0] = 0x0011; // s.s is now the active member
// at this point, reading from n or c is UB but most compilers define it
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
}
二次
每个成员都被分配,就好像它是类的唯一成员一样。
If members of a union are classes with user-defined constructors and destructors, to switch the active member, explicit destructor and placement new are generally needed: #include | (since C++11) |
---|
如果两个联合成员都是标准布局类型,那么它将定义为%27s,以检查它们在任何编译器上的公共子序列。
成员寿命
大寿命工会成员的活动开始。如果另一个成员以前是活动的,它的生命周期就结束了。
当联合的活动成员被表单的赋值表达式切换时E1 = E2
的成员访问和数组下标子表达式中出现的每个联合成员X使用内置赋值运算符或普通赋值运算符。E1
这不是一个具有非平凡或删除的默认构造函数的类,如果对X的修改在类型混叠规则下有未定义的行为,则在指定的存储中隐式创建X类型的对象;不执行初始化,并在左、右操作数的值计算之后和赋值之前对其生命周期的开始进行排序。
二次
union A { int x; int y[4]; };
struct B { A a; };
union C { B b; int k; };
int f() {
C c; // does not start lifetime of any union member
c.b.a.y[3] = 4; // OK: "c.b.a.y[3]", names union members c.b and c.b.a.y;
// This creates objects to hold union members c.b and c.b.a.y
return c.b.a.y[3]; // OK: c.b.a.y refers to newly created object
}
struct X { const int a; int b; };
union Y { X x; int k; };
void g() {
Y y = { { 1, 2 } }; // OK, y.x is active union member (9.2)
int n = y.x.a;
y.k = 4; // OK: ends lifetime of y.x, y.k is active member of union
y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,
// "y.x.b" names y.x, but X's default constructor is deleted,
// so union member y.x's lifetime does not implicitly start
}
二次
匿名工会
安匿名联盟
是一个未命名的联合定义,它不同时定义任何变量%28,包括联合类型的对象、引用或指向联合%29的指针。
union { member-specification } ; | | |
---|
匿名联合还有进一步的限制:它们不能有成员函数,不能有静态数据成员,而且它们的所有数据成员都必须是公共的。唯一允许的声明是非静态数据成员和静态[医]断言声明%28自C++14%29。
匿名工会的成员被注入到封闭的范围%28中,并且不能与在其中声明的其他名称冲突%29。
二次
int main()
{
union
{
int a;
const char* p;
};
a = 1;
p = "Jennifer";
}
二次
命名空间范围的匿名联合必须声明为静态的,除非它们出现在未命名的命名空间中。
类似工会的课程
阿工会式课程
是至少有一个匿名工会作为成员的%28非工会%29类或工会。类似联盟的类有一组变式成员
*
- 其成员匿名联盟的非静态数据成员;
- 此外,如果类似工会的类是一个联盟,那么它的非静态数据成员就不是匿名联合。
类类可用于实现标记工会...
二次
#include <iostream>
// S has one non-static data member (tag), three enumerator members (CHAR, INT, DOUBLE),
// and three variant members (c, i, d)
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 << '\n'; break;
case S::INT: std::cout << s.i << '\n'; break;
case S::DOUBLE: std::cout << s.d << '\n'; break;
}
}
int main()
{
S s = {S::CHAR, 'a'};
print_s(s
s.tag = S::INT;
s.i = 123;
print_s(s
}
二次
The C++ standard library includes std::variant, which can replace many uses of unions and union-like classes. The example above can be re-written as. #include | (since C++17) |
---|
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1940 | c++14 | anonymous unions only allowed non-static data members | static_assert also allowed |
另见
c联合申报文件
*。
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。