假如我有一个返回 std::vector
的函数:
std::vector<int> buildVector();
使用基于范围的 for
循环迭代结果似乎是很自然的:
for (int i : buildVector()) {
// ...
}
问题:这样做安全吗?
我阅读的标准(实际上是草案n4431)表明,可能不安全,虽然我很难相信委员会没有考虑到这种用法。我希望我的理解是错误的。
第6.5.4节定义了基于范围的for
:
for ( for-range-declaration : expression ) statement
使用以下的语法糖:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
range-init
是一个表达式,至少对于类类型,begin-expr
可以是__range.begin()
或begin(__range)
。
在我的buildVector
示例中,我认为range-init
会产生一个临时对象,实现允许立即销毁该对象,这意味着在绑定__range
引用之后,__range
引用可能已经失效。这意味着在评估begin-expr
之前,__range
引用可能已经失效。
当然,写成这样应该总是安全的:
std::vector<int> notATemporary = buildVector();
for (int i : notATemporary) {
// ...
}
但我希望我不必把这个问题添加到我的注意事项清单中。
for(:)
表达式中链式调用它,那么您需要通过值来存储输入范围,因为引用的寿命延长不是可传递的。使用R&&
,存储R
。 - Yakk - Adam Nevraumont`for (int i : buildVector() | boost::adaptors::reversed)`
- Llopeth