考虑一下这个 union :
union A{
int a;
struct{
int b;
} c;
};
c
和a
不是layout-compatibles类型,因此无法通过b
读取a
的值:A x;
x.c.b=10;
x.a+x.a; //undefined behaviour (UB)
对于审判1和审判2,请参见this question试用3
现在,让我们使用
std::launder
来实现它似乎不想要的功能:A x;
x.a=10;
auto p = &x.a; //(1)
x.c.b=12; //(2)
p = std::launder(p); //(2')
*p+*p; //(3) UB?
std::launder
可以更改任何内容吗?根据[ptr.launder]:粗体的句子强调了困扰我的东西。如果
p
是无效的指针值,那么如何访问任何存储字节?另一方面,读取std::launder
只是不可用。否则,可以将(2)处的
p
的值作为一个指针值,该值代表[basic.life] 的“注释”中所提到的存储区域:最佳答案
注释中明确允许使用。
无需basic.life
的 std::launder
contains the following rule:
这种“新对象是在原始对象所占的存储位置创建的”案例在此明确适用,因为:
满足所有项目符号条件,因为"potentially overlapping subobject"引用基类子对象,而 union 成员则不。 (在您链接的版本中,该项目符号直接提到了基类子对象。)
但是,即使这种解释要针对 union 而改变,该注释也特别提到std::launder
绕过了此限制。
请注意,较早版本的Standard将该子对象排除在此规则之外...但是该注释清楚地表明std::launder
也将绕过该问题。