我想push_back
在迭代向量时修改()元素,如下所示:
auto main() -> int {
std::vector<double> v { 1, 2, 3 };
for (auto& num : v) {
std::cout << num << "\n";
v.push_back(num);
}
std::cout << "===========\n";
for (const auto& num : v) {
std::cout << num << "\n";
}
}
输出为:
1
1.00938e-320
0
===========
1
2
3
1
1.00938e-320
0
为什么输出不是这样的:
1
2
3
===========
1
2
3
1
2
3
如果基于的范围只是糖:
for (auto& it{v.begin()}, it != v.end(), it++)
这里不应该有两种可能的情况吗?
-
v.end()
每次迭代都会进行评估,并且永不结束。这应该是一个无限循环。 -
v.end()
在迭代之前评估一次并且应该按我预期输出:
1
2
3
===========
1
2
3
1
2
3
7
最佳答案
1
正如您致电时所看到的:
如果操作后新的 size() 大于旧的 capacity() ,则进行重新分配,在这种情况下所有迭代器(包括 end() 迭代器)和对元素的所有引用都将失效。 否则只有end() 迭代器会失效。
(重点是我的)
只是使用迭代器的语法糖。
在 期间push_back
可能vector
需要调整大小并重新分配。在这种情况下,所有迭代器都无效,包括用作循环中的“当前”迭代器。
使用它会导致。
即使没有重新分配,检查时也会遇到问题end()
:
在循环开始前会查询一次。
与 C++17 有细微的差别。但无论如何,push_back
在循环内调用都会调用,因为end()
循环前的查询不再有效。
这意味着标准不保证程序的输出。您观察到的任何输出都是合法的。
4
-
1“
end()
每次迭代后与迭代器进行比较”具有误导性。迭代器仅在第一次迭代之前end()
确定一次。
– -
@j6t 你是对的,已改正。
– -
所有基于范围的 for 循环都调用
end
一次。C++17 中的变化是end
现在可以返回具有不同类型的标记。
– -
@PasserBy 再次阅读我发现你是对的——相应地更新了答案。
–
|
std::vector
迭代器在 上会失效push_back
。因此,您拥有的是未定义的行为。–
–
for (auto& it{v.begin()}, it != v.end(), it++)
”嗯,不完全是。这是正确的等价物:有几个重要的区别,比如end
只被评估一次。–
–
–
|