C++ 修改BOOST_FOREACH中向量的内容

C++ 修改BOOST_FOREACH中向量的内容,c++,boost,vector,foreach,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.capacit

这是一个关于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;
但是在循环的一半插入的数字4呢?如果我将类型更改为列表,则新插入的数字将被迭代。如果需要重新分配,vector push_back操作将使任何指针无效,但是在本例中没有发生这种情况。所以我想问题是,为什么在使用向量时,末端迭代器在循环之前只被计算一次,而在使用列表时,它的计算更为动态

在封面下,BOOST_FOREACH使用 遍历元素的迭代器 序列在执行循环之前, 最终迭代器缓存在本地 变量这就是所谓的吊装 这是一个重要的优化。信息技术 然而,假设最终 序列的迭代器是稳定的。信息技术 通常是,但是如果我们修改 通过添加或删除来排序 元素,而我们正在迭代 如果是这样的话,我们可能会提升自己 靠我们自己

如果不希望结束迭代器更改,请在向量上使用resize,而不是reserve


请注意,这样您就不想将_向后推,而是使用操作符[]。但是要小心越界。

boost的foreach将在迭代器==numbers.end时终止


不过要小心,调用push_back会/会使您当前拥有的任何迭代器无效。

注释中提出了一个问题,即为什么Microsoft调试运行时会在迭代过程中对向量而不是列表提出断言。原因是insert的定义与list和vector不同。请注意,push_back只是序列末尾的一个insert

< C++ >标准ISO/IEC 1488~2003 23.2.4.3,向量修饰符:

[插入时],如果没有重新分配,则插入点之前的所有迭代器和引用都保持有效

23.2.2.3,列出修改器:

[插入]不影响迭代器和引用的有效性

因此,如果您使用push_back并确信它不会导致重新分配,那么任何一个容器都可以继续使用迭代器对序列的其余部分进行迭代

但是,对于向量,使用push_返回之前获得的结束迭代器是未定义的行为


这是对这个问题的迂回回答;这是对问题评论中讨论的直接回答。

我得到一个运行您的代码Visual Studio 2008的断言。@Gman:要使它在Visual Studio 2008下工作,您必须禁用迭代器调试/D_HAS_迭代器调试=0。这不是有点违背目的吗?你在未定义的行为领域做了一些事情。修正警告,不要让它们沉默。这就像有一个编译器,当你超出数组的边界时会警告你,但是你禁用了它,这样你无论如何都可以这样做;这是个糟糕的主意;我只是说,为了让他的例子发挥作用,需要禁用迭代器调试。哎呀,我读了Ja-并假设你就是OP。愚蠢的我仍然不习惯寻找突出显示的asker名称。好吧,我想你应该知道警告的事Pright,抱歉,他在问为什么大小没有改变=改变我的答案=来自同一个链接:这个故事的寓意是在你迭代的序列中添加和删除元素之前要三思而后行。如果这样做会导致迭代器无效,请不要这样做。用一个常规的for循环来代替。啊,这解释了很多,除了为什么它适用于列表?我的猜测是。列表的结尾实际上返回NULL或类似的常量,因为列表是作为双链接列表实现的。。。因此,列表的最后一个元素被定义为元素where.next返回null,当添加/删除元素时,该值不变。我在这里走对了吗?不确定std::list用什么作为结束,但这并不重要。但是sgi站点对列表这样说:列表有一个重要的特性,即插入和拼接不会使列表元素的迭代器失效,即使删除也只会使指向被删除元素的迭代器失效。end是列表的迭代器,因此对于插入操作,它不应该无效。不是任何迭代器,只有在插入之后的迭代器才有效,除非向量超出其容量,并注意他如何使用reserve。
Testing BOOST_FOREACH
capacity = 8
1
2
3
capacity = 8