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

Pushing elements to a vector within a ranged based for loop

本文关键字:范围 for 循环 向量 元素 于范围      更新时间:2023-10-16

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

#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后添加v.reserve(12)可以解决问题。在push_back操作期间,肯定有一些与矢量重新分配以扩大其容量有关的东西。

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

基于范围 for 循环的形式为

{
    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 将导致未定义的行为,因为您使用的是不再有效的迭代器。

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

这是因为 for 循环使用的迭代器在回推期间可能会失效。在后台,向量使用缓冲区,push_back可能导致数组被重新分配。

更多参考资料在这里:http://www.cplusplus.com/forum/general/5189/

vector::p ush_back memory的引擎盖下会发生什么?