这是一个关于BOOST_FOREACH如何检查它的循环终止的问题
cout << "Testing BOOST_FOREACH" << endl;
vector<int> numbers; numbers.reserve(8);
numbers.push_back(1); numbers.push_back(2); numbers.push_back(3);
cout << "capacity = " << numbers.capacity() << endl;
BOOST_FOREACH(int elem, numbers)
{
cout << elem << endl;
if (elem == 2) numbers.push_back(4);
}
cout << "capacity = " << numbers.capacity() << endl;
给出输出
Testing BOOST_FOREACH
capacity = 8
1
2
3
capacity = 8
但是在循环中途插入的数字4怎么样?如果我将类型更改为列表,则将重复插入新插入的数字。如果需要重新分配,向量push_back操作将使任何指针无效,但是在此示例中不会发生这种情况。所以我猜的问题是为什么end()迭代器在使用向量时只被评估一次(在循环之前),但在使用列表时有更动态的评估?
答案 0 :(得分:6)
在封面下,BOOST_FOREACH使用 遍历元素的迭代器 序列。在循环执行之前, 结束迭代器缓存在本地 变量。这称为吊装,和 这是一个重要的优化。它 然而,假设结束了 序列的迭代器是稳定的。它 通常是,但如果我们修改 通过添加或删除顺序 我们正在迭代的元素 它,我们最终可能会提升自己 在我们自己的宠物上。
http://www.boost.org/doc/libs/1_40_0/doc/html/foreach/pitfalls.html
如果你不希望end()迭代器改变使用向量而不是保留。
http://www.cplusplus.com/reference/stl/vector/resize/
请注意,那么你不想使用push_back而是使用operator []。但要小心超越界限。
答案 1 :(得分:2)
在评论中提出了一个问题,即为什么Microsoft调试运行时会在向量上迭代但不在列表上引发断言。原因是insert
和list
的{{1}}定义不同(请注意vector
只是序列末尾的push_back
。)
根据C ++标准(ISO / IEC 14882:2003 23.2.4.3,向量修饰符):
[插入时],如果没有重新分配,插入点之前的所有迭代器和引用都保持有效。
(23.2.2.3,列表修饰符):
[insert]不影响迭代器和引用的有效性。
所以,如果你使用insert
(并且确定它不会导致重新分配),那么任何一个容器都可以继续使用你的迭代器迭代序列的其余部分。
但是,对于向量,使用在push_back
之前获得的end
迭代器是未定义的行为。
这是对这个问题的迂回回答;这是对问题评论中讨论的直接回答。
答案 2 :(得分:0)
boost的foreach将在iterator == numbers.end()
时终止但要小心,调用push_back可以/将使你拥有的任何当前迭代器无效。