You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::launder的作用效果是否会在其调用的表达式结束后持续生效?

示例代码

struct X { const int n; };
union U { X x; float f; };
void fun() {
  U u = {{ 1 }};
  u.f = 5.f;               // OK, creates new subobject of 'u'
  X *p = new (&u.x) X {2}; // OK, creates new subobject of 'u'
  
  if(*std::launder(&u.x.n) == 2){// condition is true because of std::launder
    std::cout << u.x.n << std::endl;  //UB here?
    }
}

结论

这段代码中std::cout << u.x.n << std::endl;属于未定义行为,程序没有确定的输出结果。

具体解释

  • std::launder的生效范围仅局限于它所在的表达式,不会对后续其他表达式的访问产生持续效果。它的核心作用是返回一个指向新创建对象的合法指针/左值,仅对当前返回值对应的访问有效,不会修改原有变量(比如本例中的u.x、u.x.n)的访问合法性。
  • 由于X结构体包含const非静态成员n,你通过placement new在&u.x位置创建新的X对象后,原有的变量名u.x不能直接用来指代这个新创建的对象,符合C++标准中需要显式调用std::launder才能合法访问新对象的场景。你在if条件中调用std::launder(&u.x.n)获得了指向新对象n成员的合法指针,所以判断条件结果确实为true,但这一调用不会让后续直接访问u.x.n的操作合法化,因此cout行存在未定义行为。
  • 如果不想每次访问都调用std::launder,你可以保存它返回的合法指针复用,比如:
    X* valid_x = std::launder(&u.x);
    if (valid_x->n == 2) {
        std::cout << valid_x->n << std::endl; // 合法操作,无未定义行为
    }
    
    只要你持有这个经过launder的合法指针,后续通过该指针的访问都不需要重复调用std::launder。但如果直接使用原变量名u.x访问,每次都需要调用std::launder才合法。

内容的提问来源于stack exchange,提问作者John Z. Li

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 07:57:02