什么使工会会员活跃?
我已经阅读了C ++ 14标准的第9.5章(关于工会的第9.5章),但我还没有找到使工会成员活跃的明确答案。
有一张纸条:
通常,必须使用显式析构函数调用和placement new 运营商改变工会的活跃成员。
例如,
union U {
int i;
short s;
} u;
new(&u.i) int(42);
好的,放置新的更改活动成员,它很清楚。但是在处理具有普通构造函数的类型时,我们通常不会使用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;
之后,有效成员未更改为a
(我认为),UB也可以int x = u.a.i0;
吗?
C ++ 17是否改进了活跃成员的描述?
答案 0 :(得分:7)
在C ++ 17中,添加了一个段落,明确讨论了像u.i = 42
这样的案例:
[class.union] / 5 当赋值运算符的左操作数涉及指定联合成员的成员访问表达式(8.2.5)时,它可能会从该联合成员的生命周期开始,如下所述。对于表达式
E
, 定义S(E)
子表达式的E
集,如下所示:(5.1) - 如果
E
的格式为A.B
,则S(E)
包含S(A)
的元素,如果A.B
还包含B
命名非类,非数组类型的联合成员,或具有未删除的普通默认构造函数的类类型的联合成员,或者此类型的数组。(5.2) - 如果
E
的格式为A[B]
且被解释为内置数组下标运算符,则S(E)
为S(A)
A
如果S(B)
是数组类型,则为数组类型B
,否则为空。(5.3) - 否则,
S(E)
为空。在
E1 = E2
形式的赋值表达式中,它使用内置赋值运算符(8.18)或普通赋值运算符(15.8),用于X
的每个元素S(E1)
,如果X
的修改在6.8下具有未定义的行为,则在指定的存储中隐式创建X
类型的对象;不执行初始化,并且在左右操作数的值计算之后和赋值之前对其生命周期的开始进行排序。 [注意:这会结束以前活动成员的生命周期,如果有的话(6.8)。 -end note ]
(接下来是一个很长的例子,我懒得格式化,但你可以看到here。)