g++编译时[-Wdangling-reference]警告是否为误报?
GCC 13.x中
-Wextra触发的范围视图悬垂引用警告是误报吗? 以下是测试代码:
#include <iostream> #include <vector> #include <ranges> int main() { std::vector<int> a{ 1, 2, 3, 4, 5 }; std::span<const int> b{ a }; for ( auto i : b | std::views::drop(1) ) std::cout << i << '\n'; }
使用-Wextra选项编译上述代码时,GCC 13.1或13.2会发出如下警告:
<source>: In function 'int main()': <source>:11:40: warning: possibly dangling reference to a temporary [-Wdangling-reference] 11 | for ( auto i : b | std::views::drop(1) ) | ^ <source>:11:40: note: the temporary was destroyed at the end of the full expression 'std::ranges::views::__adaptor::operator|<_Partial<std::ranges::views::_Drop, int>, std::span<const int>&>(b, ((const std::ranges::views::__adaptor::_RangeAdaptor<std::ranges::views::_Drop>*)(& std::ranges::views::drop))->std::ranges::views::__adaptor::_RangeAdaptor<std::ranges::views::_Drop>::operator()<int>(1))'
其他编译器及旧版本GCC均无此提示,请问这属于误报还是遗漏了什么细节?
回答
这是GCC 13.x版本的误报,核心原因如下:
std::views::drop作为范围适配器,返回的视图对象仅持有对原始std::span的引用,而span引用的vector a在main函数栈上,生命周期完全覆盖整个for循环,不存在悬垂风险。- 对于基于范围的
for循环,标准要求循环会将范围表达式的结果绑定到一个隐式的引用变量上,该变量的生命周期会持续到循环结束。也就是说,b | std::views::drop(1)产生的临时视图对象不会在完整表达式结束时销毁,而是会存活到循环执行完毕,所以不会出现引用悬垂的问题。
这个问题属于GCC在范围视图警告逻辑上的实现缺陷,后续的GCC 14版本已经修复了该误报。
内容的提问来源于stack exchange,提问作者Bob__
相关产品推荐
相关产品推荐

