考虑以下代码:
#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
编译它,g++ 13.2(或 13.1)会发出此警告:
<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))'
其他编译器和以前版本的 g++ 不会抱怨(参见例如 https://godbolt.org/z/Pf9YoWv57)。
这是误报还是我遗漏了什么?
range-for 循环大致等价于以下内容:
{
<init-statement>
auto && __range = <range-expression> ;
auto __begin = <begin-expr> ;
auto __end = <end-expr> ;
for ( ; __begin != __end; ++__begin)
{
<range-declaration> = *__begin;
<loop-statement>
}
}
在您的情况下,
<range-expression>
是b | std::views::drop(1)
,它返回一个临时对象,然后循环将引用该对象。 range-for
循环将延长由 <range-expression>
创建的任何临时对象的生命周期,直到循环结束,但是,根据您使用的 C++ 版本和编译器,循环可能会或可能不会延长任何中间对象的生命周期在 <range-expression>
. 内创建的临时文件
这可能是编译器警告您的内容。