范围循环中的悬空引用疑问:该代码是否存在未定义行为?
问题解答
代码是否存在未定义行为?
结论:这段代码在任何C++标准版本中都不存在悬空引用导致的未定义行为,你的判断是错误的。
详细分析
范围for循环的生命周期规则
范围for会隐式创建转发引用__range,用来绑定范围表达式的结果。根据C++标准:- 若范围表达式返回临时对象(此处
bar().foo()返回的std::vector<int>临时对象),该临时对象的生命周期会被延长至循环结束,这个规则从C++11起就生效。 - 你提到的「临时对象生命周期无法传递延长」规则,适用于“用绑定临时的引用去初始化另一个引用”的场景,但这里的
__range是直接绑定到vector临时对象,不存在传递,因此生命周期延长规则直接适用。
- 若范围表达式返回临时对象(此处
范围表达式内部临时对象的影响
bar()返回的A类临时对象,在C++23之前确实会在foo()调用完成后销毁,但这个临时对象和foo()返回的vector毫无关联——vector是值返回的独立临时对象,A对象的销毁不会影响vector的内存有效性。Sanitizer未检测到问题的原因
这段代码中的vector是空的,循环体根本不会执行,没有任何实际的内存访问操作。Sanitizer只能检测实际发生的内存违规,自然无法发现所谓的“问题”。即使给vector添加元素,循环中访问el,也不会触发Sanitizer报警,因为vector的生命周期已被延长到循环结束。C++23的规则补充
C23进一步优化了规则:范围表达式内部的所有临时对象(包括bar()返回的A对象)的生命周期都会被延长至循环结束,但这只是让规则更严谨,对这段代码的合法性没有本质影响——因为在C23之前,核心的vector临时对象已经被正确延长生命周期了。
内容的提问来源于stack exchange,提问作者getsoubl
相关产品推荐
相关产品推荐

