C++ 中嵌套增强型 for 循环的范围

Scoping of nested enhanced for loops in c++

本文关键字:循环 范围 for 增强型 嵌套 C++      更新时间:2023-10-16

这是我的代码来生成一个集合的功率集,但它没有按预期工作。

#include <string>
#include <stdio.h>
#include <vector>
using namespace std;
vector<vector<int>> powerSet(vector<int> set){
    vector<vector<int>> result;
    vector<int> emptySet;
    result.push_back(emptySet);
    for(int i: set){
        for(vector<int> subSet:result){
            subSet.push_back(i);
            result.push_back(subSet);
        }
    }
    return result;
}
int main(){
    vector<int> a = {1, 2, 3};
    vector<vector<int>> r = powerSet(a);
    for(vector<int> v: r){
        for(int n : v){
            printf("%d ", n);
        }
        printf("n");
    }
    return 0;
}

此代码打印:


1阿拉伯数字
阿拉伯数字

3
3
3
3

在我稍微改变它之后,它就可以工作了。这是我的工作代码:

#include <string>
#include <stdio.h>
#include <vector>
using namespace std;
vector<vector<int>> powerSet(vector<int> set){
    vector<vector<int>> result;
    vector<int> emptySet;
    result.push_back(emptySet);
    for(int i: set){
        vector<vector<int>> moreSets; // here is the changes
        for (vector<int> subSet: result){
            subSet.push_back(i); 
            moreSets.push_back(subSet); // here is the changes
        }
        result.insert(result.end(), moreSets.begin(), moreSets.end()); // here is the changes        }
    return result;
}
int main(){
    vector<int> a = {1, 2, 3};
    vector<vector<int>> r = powerSet(a);
    for(vector<int> v: r){
        for(int n : v){
            printf("%d ", n);
        }
        printf("n");
    }
    return 0;
}

谁能告诉我第一个代码的问题是什么?非常感谢!

在第一个代码中,请看下面的代码

for(vector<int> subSet:result){
    subSet.push_back(i);
    result.push_back(subSet);
}

您正在更改要迭代的result。这最终不会很好,甚至可能导致无限循环、程序崩溃等。

基于范围的 for 循环在 begin(container)end(container) 之间迭代,这是通过依赖于参数的查找找到的(不执行非 ADL 查找)。

如果在loop_statement中更改容器,则以前的(内部使用的)迭代器无效,从而导致未定义的行为。

有关更多详细信息,请阅读 6.5.4 基于范围的 for 语句 [stmt.ranged]


相关文章: 在基于范围的 for 循环中擦除容器中的元素

当您追加到

结果时,这将在发生重新分配时使迭代器失效,并在超出矢量容量时发生重新分配。

        for(vector<int> subSet:result){
            subSet.push_back(i);
            result.push_back(subSet);
        }

如果在开始时通过成员函数在向量结果中保留足够的空间reserve ()它应该可以工作。 我没有检查标准,但我很确定迭代器应该保持有效,因为您不会在结束迭代器之前删除或插入任何元素,并且该元素在循环开始时初始化。

如果我没记错的话,这就是矢量保证。 并不是说我鼓励你写这样的代码。

编辑:

好的,我会收回来的。 显然,结束迭代器已失效。

如果向量有足够的空间(通过保留创建),std::vector::insert() 是否会使迭代器失效?