是什么让工会会员活跃起来?
What makes a union member active?
是什么让工会成员活跃起来?
我已经阅读了 C++14 标准的第 9.5 章(关于联合的那一章),但是对于什么使联合成员活跃,我还没有找到明确的答案。
有备注:
In general, one must use explicit destructor calls and placement new
operators to change the active member of a union.
例如,
union U {
int i;
short s;
} u;
new(&u.i) int(42);
好的,placement new 改变活跃成员,很清楚了。但是在处理具有普通构造函数的类型时,我们通常不使用 placement new。
operator=
是否更换没有UB的活跃会员?
u.i = 42;
这里,operator=
调用了一个未构造的对象。定义好了吗?
这个呢?
struct A {
int i0;
int i1;
};
union U {
A a;
short s;
} u;
是什么让 a
成为 u
的活跃成员?同时设置 i0
和 i1
是否足够?
u.a.i0 = 42;
u.a.i1 = 99;
如果我写:
u.a.i0 = 42; // supposedly this doesn't change the active member to a, as i1 isn't set
int x = u.a.i0; // is it fine to read from a.i0? a is not an active member supposedly
u.a.i0 = 42;
之后,active成员没有改成a
(我觉得),所以做int x = u.a.i0;
是不是UB?
C++17 是否改进了活跃成员的描述?
在 C++17 中,添加了一段明确讨论 u.i = 42
:
等情况
[class.union]/5 When the left operand of an assignment operator involves a member access expression (8.2.5) that nominates a union member, it may begin the lifetime of that union member, as described below. For an expression E
,
define the set S(E)
of subexpressions of E
as follows:
(5.1) — If E
is of the form A.B
, S(E)
contains the elements of S(A)
, and also contains A.B
if B
names a union member of a non-class, non-array type, or of a class type with a trivial default constructor that is not deleted, or an array of such types.
(5.2) — If E
is of the form A[B]
and is interpreted as a built-in array subscripting operator, S(E)
is S(A)
if A
is of array type, S(B)
if B
is of array type, and empty otherwise.
(5.3) — Otherwise, S(E)
is empty.
In an assignment expression of the form E1 = E2
that uses either the built-in assignment operator (8.18) or a trivial assignment operator (15.8), for each element X
of S(E1)
, if modification of X
would have undefined behavior under 6.8, an object of the type of X
is implicitly created in the nominated storage; no initialization is performed and the beginning of its lifetime is sequenced after the value computation of the left and right operands and before the assignment. [ Note: This ends the lifetime of the previously-active member of the union, if any (6.8). —end note ]
(后面是一个较长的示例,我懒得正确格式化,但您可以看到 here。)
是什么让工会成员活跃起来?
我已经阅读了 C++14 标准的第 9.5 章(关于联合的那一章),但是对于什么使联合成员活跃,我还没有找到明确的答案。
有备注:
In general, one must use explicit destructor calls and placement new operators to change the active member of a union.
例如,
union U {
int i;
short s;
} u;
new(&u.i) int(42);
好的,placement new 改变活跃成员,很清楚了。但是在处理具有普通构造函数的类型时,我们通常不使用 placement new。
operator=
是否更换没有UB的活跃会员?
u.i = 42;
这里,operator=
调用了一个未构造的对象。定义好了吗?
这个呢?
struct A {
int i0;
int i1;
};
union U {
A a;
short s;
} u;
是什么让 a
成为 u
的活跃成员?同时设置 i0
和 i1
是否足够?
u.a.i0 = 42;
u.a.i1 = 99;
如果我写:
u.a.i0 = 42; // supposedly this doesn't change the active member to a, as i1 isn't set
int x = u.a.i0; // is it fine to read from a.i0? a is not an active member supposedly
u.a.i0 = 42;
之后,active成员没有改成a
(我觉得),所以做int x = u.a.i0;
是不是UB?
C++17 是否改进了活跃成员的描述?
在 C++17 中,添加了一段明确讨论 u.i = 42
:
[class.union]/5 When the left operand of an assignment operator involves a member access expression (8.2.5) that nominates a union member, it may begin the lifetime of that union member, as described below. For an expression
E
, define the setS(E)
of subexpressions ofE
as follows:(5.1) — If
E
is of the formA.B
,S(E)
contains the elements ofS(A)
, and also containsA.B
ifB
names a union member of a non-class, non-array type, or of a class type with a trivial default constructor that is not deleted, or an array of such types.(5.2) — If
E
is of the formA[B]
and is interpreted as a built-in array subscripting operator,S(E)
isS(A)
ifA
is of array type,S(B)
ifB
is of array type, and empty otherwise.(5.3) — Otherwise,
S(E)
is empty.In an assignment expression of the form
E1 = E2
that uses either the built-in assignment operator (8.18) or a trivial assignment operator (15.8), for each elementX
ofS(E1)
, if modification ofX
would have undefined behavior under 6.8, an object of the type ofX
is implicitly created in the nominated storage; no initialization is performed and the beginning of its lifetime is sequenced after the value computation of the left and right operands and before the assignment. [ Note: This ends the lifetime of the previously-active member of the union, if any (6.8). —end note ]
(后面是一个较长的示例,我懒得正确格式化,但您可以看到 here。)