模板实参推导中生成的临时对象经lambda引用捕获延长生存期是否会引发未定义行为?
模板实参推导中生成的临时对象经lambda引用捕获延长生存期是否会引发未定义行为?
好问题!这确实是C++里藏得比较深的细节坑,咱们一点点拆解着看:
首先直接给结论:你贴的这段代码完全符合C++标准,是安全的,不会出现未定义行为。
咱们来一步步理清楚背后的规则:
- 当你在
main里调用foo(std::string("hello"))时,std::string("hello")是一个临时对象。模板实参推导会把T推导为std::string,所以foo的参数const T& ref其实就是const std::string& ref,这个引用会直接绑定到刚才的临时字符串对象上。 - 根据C++标准的核心规则:临时对象绑定到函数的const左值引用参数时,它的生存期会被延长到整个函数调用的生命周期——也就是从进入
foo函数开始,到foo执行完毕返回之前,这个临时字符串都不会被销毁。 - 再看lambda部分:你用
[&]捕获了ref,本质是捕获了这个指向临时对象的引用。但关键是,你在foo函数内部直接调用了lambda(),这时候临时对象的生存期还没结束(因为foo还在运行),所以引用指向的对象是完全有效的,输出hello的行为是安全的。
这里容易产生的误区是:会不会因为模板实参推导的存在,打破了临时对象的生存期延长规则?答案是不会。模板推导只是帮我们确定了T的类型,并没有改变“临时对象绑定到函数const左值引用参数”这个核心绑定关系,生存期延长的规则依然正常生效。
额外提个醒:如果你的代码改成把这个lambda从foo里返回出去,之后在main里调用的话,那肯定会触发未定义行为——因为临时对象在foo返回时就已经销毁了,lambda里的引用会变成悬垂引用。但你现在的代码是在foo内部直接调用lambda,完全没问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

