使用c++ 11基于范围的for循环和右值range-init是否安全?
Is it safe to use a C++11 range-based for-loop with an rvalue range-init?
假设我有一个返回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
仅为( expression )
,并且至少对于类类型,begin-expr
为__range.begin()
或begin(__range)
,等等。
在我的buildVector
示例中,我认为range-init
产生了一个临时对象,允许在绑定__range
引用后立即销毁它。这意味着在计算begin-expr
的时候,__range
引用可能已经悬空了。
当然,这样写应该总是安全的:
std::vector<int> notATemporary = buildVector();
for (int i : notATemporary) {
// ...
}
但是我希望我不需要把这个添加到我的陷阱列表中
是的,非常安全。
从[class.temporary]/4 - 5:在两种上下文中,临时变量在fulexpression末尾的不同位置被销毁。第一个上下文是在调用默认构造函数[…]
时。第二个上下文是当引用绑定到临时对象时。引用所指向的临时对象引用被绑定到的子对象的完整对象(即临时对象)持续存在引用的生命周期,除了:
- 在构造函数的参数初始化式[…]
中临时绑定到引用成员- 函数调用中临时绑定到引用参数[…]
- 函数返回语句中临时绑定返回值的生命周期[…]
- 在new-initializer[…]
中临时绑定到引用
这些例外都不适用。因此,临时变量在引用__range
的生命周期内持续存在,即整个循环。
相关文章:
- 如何循环打印顶点结构
- 如何在C++中从两个单独的for循环中添加两个数组
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 正在尝试了解输入验证循环
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 循环后如何继续阅读
- Ardunio UNO解决了多个重叠的定时器循环
- Eigen如何在容器循环中干净地附加矩阵
- 在某些循环内使用vector.push_back时出现分段错误
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 为什么基于范围类型的大括号上循环init列表是非法的c++
- C++ 通过 range for 循环将整数输入到矢量中;随机 0
- 删除for-range循环中项目的最快方法
- c++11中一个XMLElement类的基于Tricky-range的循环实现
- C++11:基于范围的 for 语句:"range-init"生命周期?
- 如何在range for循环中使用begin()和end()
- 强制auto为range for循环中的引用类型
- 使用 range-for 循环:函数调用的参数太少,未指定单个参数'a'
- 从整数索引的for循环枚举到range-for
- 使用c++ 11基于范围的for循环和右值range-init是否安全?