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

关于将临时对象作为const T&传递并绑定到类引用的副作用及相关未定义行为的技术问询

问题解答:auto x = A("E")._s 是否会触发未定义行为?

答案是肯定存在,这条语句确实可能陷入未定义行为(UB),具体场景完全取决于类A的构造函数实现,咱们结合你给出的两种构造场景逐一分析:


场景1:类A通过左值引用接收构造参数

先看对应的代码实现:

struct A{ 
    const std::string& _s; 
    A(const std::string& s): _s(s){} 
}; 

int main(void){ 
    auto x = A("E")._s; 
    std::cout << x << '\n'; 
}

这里的问题根源和你提到的A a("E")案例完全一致:

  • 字符串字面量"E"会被隐式转换成一个临时的std::string对象,用来初始化构造函数的参数s。
  • 这个临时std::string的生命周期只持续到完整表达式结束——也就是A("E")._s这条语句执行完毕的瞬间。
  • auto会根据_s的类型推导为const std::string&,所以x会绑定到这个已经被销毁的临时对象上。后续访问x(比如std::cout那一行)就是在访问悬垂引用,属于标准定义的未定义行为。

注:如果显式让x推导为值类型(比如auto x = static_cast<const std::string>(A("E")._s);),会在临时对象销毁前完成拷贝,这种情况就不会有问题,但默认的auto推导会保留引用属性,直接踩坑。


场景2:类A通过值传递接收构造参数

也就是你注释里的那个构造函数版本:

struct A{ 
    const std::string& _s; 
    A(const std::string s): _s(s){} // 按值传参
}; 

int main(void){ 
    auto x = A("E")._s; 
    std::cout << x << '\n'; 
}

这种情况编译器甚至会提前给你警告:提示你将引用成员绑定到了构造函数的临时参数s上。原因是:

  • 按值传参时,"E"会被拷贝到构造函数的局部参数s中,这个s是构造函数内的临时对象,生命周期只在构造函数执行期间。
  • 当A的临时对象创建完成后,s已经被销毁,_s直接变成悬垂引用。
  • 此时不管auto x推导成引用还是值,只要尝试访问x(哪怕是拷贝x的过程),都是在访问已经销毁的内存区域,同样属于未定义行为。

简单总结:只要类A的引用成员_s绑定的是临时对象(不管是构造函数参数引用的临时,还是构造函数值参数本身的临时),那么auto x = A("E")._s这条语句后续访问x时,必然会触发未定义行为。只有当_s绑定的是生命周期超过当前完整表达式的对象(比如全局变量、栈上持久存在的对象)时,这条语句才是安全的,但这已经超出了你给出的场景范围。

内容的提问来源于stack exchange,提问作者Pol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:13:11