修改BOOST_FOREACH中向量的内容

时间:2009-11-26 02:30:49

标签: c++ boost vector foreach

这是一个关于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()迭代器在使用向量时只被评估一次(在循环之前),但在使用列表时有更动态的评估?

3 个答案:

答案 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调试运行时会在向量上迭代但不在列表上引发断言。原因是insertlist的{​​{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可以/将使你拥有的任何当前迭代器无效。