在遍历动态向量时使用auto的异常行为
Unusual behavior with auto while traversing a dynamic vector
我正在遍历一个带有auto(附加代码)的向量。在遍历时,我还在后面添加了一些元素。我没有预料到我得到的输出。
#include <iostream>
#include <vector>
using namespace std;
vector <int> dynamic_vector;
void access( )
{
for ( auto i : dynamic_vector ) {
if ( i == 3 ) {
dynamic_vector.push_back( 4 );
dynamic_vector.push_back( 5 );
}
cout << i << endl;
}
}
int main() {
dynamic_vector.push_back( 1 );
dynamic_vector.push_back( 2 );
dynamic_vector.push_back( 3 );
access( );
return 0;
}
输出:1
2
3
我期望从1到5的所有数字都会被打印出来。我不明白怎么用汽车穿越?
除了宋元尧回答中指出的问题外,您呈现的代码是未定义行为。首先,有可能因为push_back
而需要重新分配vector,然后所有迭代器都无效,因此对循环变量进行自增是未定义的行为。
查看push_back的文档:
如果new size()大于capacity(),则所有迭代器和引用(包括过端迭代器)无效。否则,只有过末端迭代器失效。
,我想说,在任何情况下,在基于范围的for语句中向vector对象追加操作都是未定义的行为,因为end迭代器总是无效的。基于范围的for存储了初始end()
迭代器的副本,并且该迭代器在第一个push_back
之后失效。这与您的输出相匹配,因为它仍然指向三元素向量的原始末端。但是,您不应该依赖于此行为。
不幸的是,我在标准中找不到"无效迭代器"语义的严格定义。§24.2.1.11规定无效迭代器可以是单数,但只声明对其解引用可能是未定义的行为。没有语义可以比较它们,但考虑到vector的一种实现是使用内部存储之后的下一个内存地址,并且当vector重新分配时该地址会发生变化,我认为循环是未定义行为。
这叫做基于范围的for循环。
基于range的for语句[stmt.range]:在每种情况下,基于范围的for语句都相当于
{ auto && __range = range-init; for ( auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin ) { for-range-declaration = *__begin; statement } }
注意等效的伪代码,__end
(和__begin
)将只在循环开始时设置一次。在您的示例中,在循环的最后一次push_back操作之后,迭代器可能无效。如果是,则它们的增量和比较将依赖于实现。这意味着,作为一种可能性,__end
和__begin
将保持不变,循环计数不会改变。
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 如何在自定义类中启用'auto loops'?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 在遍历动态向量时使用auto的异常行为