将元素推送到基于范围的for循环内的向量

时间:2016-01-21 20:23:06

标签: c++ c++11 vector

有人可以向我解释为什么这个简单的代码:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v = {0, 1, 2, 3, 4, 5};

    for(auto i: v)
    {
        std::cout << i << ' ';
    }

    std::cout << std::endl;

    for(auto i: v)
    {
        std::cout << i << ' ';
        v.push_back(4);
    }

    std::cout << std::endl;

    for(auto i: v)
    {
        std::cout << i << ' ';
    }
}

此处发布的代码:http://cpp.sh/5kxdu

输出:

0 1 2 3 4 5 
0 0 2 3 4 5 
0 1 2 3 4 5 4 4 4 4 4 4 

虽然我期待:

0 1 2 3 4 5 
0 1 2 3 4 5 
0 1 2 3 4 5 4 4 4 4 4 4 

我知道在for循环期间修改向量是不好的(当我点击它时只是尝试别的东西)。在v声明后,v.capacity()会返回6,很明显,在声明v.reserve(12)后添加v会解决问题。肯定有一些与向量重新分配有关的东西,以便在push_back操作期间扩展其容量。

但是我想知道这是否只是一个未确定的行为而且我很幸运,只有第二个元素是错误的,或者这是可预测和可解释的(考虑for循环如何工作)。

3 个答案:

答案 0 :(得分:7)

ranged based for loop的格式为

{
    auto && __range = range_expression ; 
    for (auto __begin = begin_expr,
         __end = end_expr; 
         __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
    } 
} 

并在循环开始时设置beginend迭代器。当您调用push_back时,它总是使end迭代器无效,如果size增长大于capacity,则所有迭代器都将失效。

因此,当您使用不再有效的迭代器时,使用push_back会导致未定义的行为。

答案 1 :(得分:2)

在第一个push_back之后,向量重新分配其缓冲区,并且在ranged for循环中的迭代器无效。

答案 2 :(得分:1)

这是因为for循环使用的迭代器在回退期间可能无效。在引擎盖下,向量使用缓冲区,而push_back可以使数组重新分配。

此处有更多参考资料: http://www.cplusplus.com/forum/general/5189/

What happens under the hood of vector::push_back memory wise?