使用std::launder从不活跃union成员指针获取活跃成员指针是否可行?
关于std::launder在union跨成员访问的问题解答
首先直接给出结论:是的,当short_str不是union的活跃成员时,std::launder(short_str+15)会返回指向size_r[7]的指针,下面结合标准条款和你的场景详细解释:
核心依据:[ptr.launder]/3条款
你提到的条款是关键判断依据:
若某存储字节属于对象Y占用的存储、与Y指针可互转换的对象,或Y为数组元素时其直接所属的数组对象,则该字节可通过指向对象Y的指针访问。
在你的场景里:
short_str[15]和size_r[7]是同一个存储字节(ABI明确规定地址相同),这个字节属于活跃成员large_str的子对象size_r的存储。short_str是union的非活跃成员,但它的指针与union对象的指针可互转换(union的所有成员共享同一块存储,成员指针与union指针天然满足可互转换条件)。
std::launder的作用逻辑
直接解引用short_str+15属于未定义行为,因为short_str不是当前活跃成员。但std::launder的设计目的就是处理这种「存储位置上存在另一个活跃对象」的场景:
它会识别到short_str+15指向的字节实际属于活跃对象size_r[7]的存储,同时由于short_str的指针与union指针可互转换,完全符合[ptr.launder]/3的访问条件,因此std::launder会返回一个指向size_r[7]的有效合法指针,此时解引用该指针是合规的。
补充说明
ABI的明确规定是整个推论的前提——它保证了short_str[15]和size_r[7]的地址重合,让我们可以确定两者对应同一个存储位置。如果没有ABI的约束,我们不能默认union不同成员的特定位置地址相同,但既然ABI已经明确,这个场景就完全符合C++标准的要求。
内容的提问来源于stack exchange,提问作者Oliv
相关产品推荐
相关产品推荐

