在基于范围的循环 c++11 期间将元素添加到向量
我使用了 C++11 标准提供的新的基于范围的 for 循环,并提出了以下问题:假设我们使用范围迭代 vector<>
-基于 for
,我们在这个迭代过程中在向量的末尾添加了一些元素.因此,循环何时结束?
例如,看这个代码:
#include #include <向量>使用命名空间标准;int main() {向量<无符号>测试({1,2,3});for(auto &num : test) {cout<<数量<<"";如果(数量 % 2)test.push_back(num + 10);}cout<<"
";for(自动&num : 测试)cout<<数量<<"";返回0;}
我使用-std=c++11"标志测试了 G++ 4.8 和 Apple LLVM 版本 4.2 (clang++),输出是(对于两者):
1 2 31 2 3 11 13
请注意,尽管我们向其中添加了其他元素,但第一个循环在原始向量的末尾终止.似乎 for-range 循环仅在开始时评估容器结束.事实上,这是 range-for 的正确行为吗?是否由委员会指定?我们可以相信这种行为吗?
注意,如果我们改变第一个循环
for(vector::iterator it = test.begin(); it != test.end(); ++it)
迭代器无效并产生分段错误.
解决方案不,您不能依赖这种行为.修改循环内的向量会导致未定义的行为,因为当修改向量时,循环使用的迭代器会失效.
基于范围的for循环
for ( range_declaration : range_expression) loop_statement
本质上等同于
{汽车&&__range = range_expression ;for (auto __begin = std::begin(__range),__end = std::end(__range);__开始!= __结束;++__开始){range_declaration = *__begin;循环语句}}
当您修改向量时,迭代器 __begin
和 __end
不再有效并且取消引用 __begin
会导致未定义的行为.>
I have used the new range-based for loop provided by C++11 standard and I came up with the following question: suppose that we iterate over a vector<>
using the range-based for
, and we add some element in the end of the vector during this iteration. Thus, when do the loop end?
For instance, see this code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<unsigned> test({1,2,3});
for(auto &num : test) {
cout << num << " ";
if(num % 2)
test.push_back(num + 10);
}
cout << "
";
for(auto &num : test)
cout << num << " ";
return 0;
}
I tested G++ 4.8 and Apple LLVM version 4.2 (clang++) with "-std=c++11" flag, and the output is (for both):
1 2 3
1 2 3 11 13
Note that the first loop terminates in the end of original vector, although we add other elements to it. It seems that the for-range loop evaluate the container end in beginning only. Is this, in fact, the correct behavior of range-for? Is it specified by the committee? Can we trust in this behavior?
Note that if we change the first loop by
for(vector<unsigned>::iterator it = test.begin(); it != test.end(); ++it)
with invalid the iterators and come up with a segmentation fault.
解决方案No you cannot rely on this behaviour. Modifying the vector inside the loop results in undefined behaviour because the iterators used by the loop are invalidated when the vector is modified.
The range based for loop
for ( range_declaration : range_expression) loop_statement
is essentially equivalent to
{
auto && __range = range_expression ;
for (auto __begin = std::begin(__range),
__end = std::end(__range);
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
When you modify the vector, the iterators __begin
and __end
are no longer valid and the dereferencing __begin
results in undefined behaviour.
相关文章