为什么在循环中向量不更新?

5

我希望更新向量“v”,以便我可以从计数0-100进行迭代。

我知道这是不被允许的,但如果我只想这样做呢? 有什么办法吗?

int main() {
    // your code goes here
    vector<int> v;
    v.push_back(1);
    int count = 0;

    for(int elem: v){
        if(count<100)
        v.push_back(count);
        count++;
    }

    for(int elem: v)
    cout << elem << endl;

    return 0;
}

输出结果为:
1    
0

2
代码的输出是预期的。我不明白你想做什么。for (int i = 0; i < 100; i++) - Neil Kirk
2
@NeilKirk 他认为在 for(int elem: v) 中,v 的长度会被更新。 - Thomas Ayoub
@Thomas 哦,我明白了,我没有注意到! - Neil Kirk
2
这是一种特别晦涩的编码方式。我希望这只是一个例子,而不是你经常做的事情。 - Borgleader
2
push_back 在重新分配内存时会使所有迭代器失效,并且在所有情况下都会使 past-the-end 迭代器失效。你的代码存在 UB,因为在底层,range-for 循环会增加一个可能无效的迭代器,然后将其与一个明确无效的迭代器进行比较。 - T.C.
@T.C. 我认为这应该是一个答案(假设这是 OP 的真正问题,而不仅仅是想要用 0..100 填充向量的方法)。编辑:user2079303 将其添加到他们的答案中。 - Dettorer
5个回答

11

正如你可以从范围for循环的定义中看到的那样,end_expr在迭代之间不会更新。因此,您只有一次迭代。push_back会使v.end()(即链接页面中描述的end_expr)无效,因此您实际上是有未定义的行为。

将vector填充为0..100的最简单方法可能是:

vector<int> v(101);
std::iota(v.begin(), v.end(), 0);

2
你需要的是(101),而不是{101} - T.C.

3
你应该使用这段代码代替。
int count = 0;
while (v.size() < 100) {
   v.push_back(count++)
}

迭代遍历向量时不允许修改其内容。

我知道这是不允许的,但如果我只想这样做怎么办? - P0W
1
对于v中的每个元素int elem: cout << elem << endl; 如果count<100,则执行以下操作 v.push_back(count); count++; } 这个if循环是这样的吗?@nnesterov - Rupesh Yadav.
1
谢谢大家,我不知道如何在注释部分缩进 :( 对此感到抱歉。 - Rupesh Yadav.

2

使用您的代码:

for(int elem: v){
    if(count<100)
        v.push_back(count);
    count++;
}

就像使用这个:

int i = v.size();
for(int j = 0; j < i; j++){
     v.push_back(j);
}

我并不确定为什么... v.size()可能会保存在内存中,以便进行优化和数据保护。

在OP评论后进行编辑:

试一试这个。

int i = v.size();
for(int j = 0; j < i; j++){
    if(j<100)
        i = v.size();
    v.push_back(count);
}

你是指 v.size() 吗? - Neil Kirk
@NeilKirk 是的,我的错。 - Thomas Ayoub
它将使用iterator而不是索引(因此会导致UB)。 - Jarod42
1
大家好,我在寻找一种方法,在for循环中改变向量的长度,以便我可以指向新插入的值,但我知道这是不允许的 :),没有更多了。 - Rupesh Yadav.

2

最有效的方法执行此操作

vector<int> v;
v.resize(100);
for(unsigned int i = 0; i < v.size(); i++)
{
    v[i] = i;
}

同上。

1
“最有效”的意思是什么? - Sambuca
push_back方法是强制性的,因此我们可以首先设置向量的大小,然后再分配值。我认为iota在C++11之前不存在?我是对的吗?因此,如果您使用旧版本的C ++,则无法使用iota。 - Burak Hamuryen

2
一个基于范围的for循环生成类似于下面的代码:
{
auto && __range = range_expression ; 
    for (auto __begin = begin_expr,__end = end_expr; __begin != __end; ++__begin) { 
        range_declaration = *__begin; 
        loop_statement 
  } 
} 

正文:

正如你所看到的,当你迭代容器时,范围不会被更新。

此外,由于你正在将值推回到你的vector中,如果发生调整大小,这些迭代器将被无效化,因此你很可能最终得到未定义的行为。

请参阅@user2079303提供的更好方法来填充你的vector


1
实际上,我的意图不是像那样填充向量,而是我想知道是否有办法在循环中更新向量范围? - Rupesh Yadav.
我真的不认为在循环内部使用范围是一个好主意,即使这是可能的。你为什么想这样做呢? - Sambuca
1
我想在向量中插入元素并同时迭代它,但这在向量中不可能,但在std::list中可以。我只是想尝试一下stackoverflow能否找到某种方法:p - Rupesh Yadav.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接