首页 > 解决方案 > 基于 C++ 范围的 for 循环和元素副本

问题描述

我想生成给定向量的所有子集:

vector<vector<int>> findSubsets(const vector<int> &nums) {
        vector<vector<int>> subsets;
        subsets.push_back(vector<int>{}); //empty set
        for (auto current_num : nums)
        {
            //add current_num to all existing subsets
            int n = subsets.size();
            for (int i = 0; i < n; i++) {
                vector<int> set(subsets[i]);
                set.push_back(num);
                subsets.push_back(set);
            }
        }
        return subsets;
    }

我想使用基于范围的 for 循环来迭代所有子集,它会给出不同的结果:

vector<vector<int>> findSubsets(const vector<int> &nums) {
        vector<vector<int>> subsets;
        subsets.push_back(vector<int>{}); //empty set
        for (auto current_num : nums)
        {
            //add current_num to all existing subsets
            for (vector<int> subset : subsets)
            {
                subset.push_back(current_num);
                subsets.push_back(subset);
            }
        }
        return subsets;
    }

但这并没有达到我的预期。我错过了什么?

标签: c++

解决方案


正如@Fureeish 在评论中提到的,第二个版本的一个问题是在迭代子集向量时插入子集向量。

for (vector<int> subset : subsets)
 {
   subset.push_back(current_num);
   subsets.push_back(subset);  // Should not modify vector while iterating on it
 }

range 语句扩展为:

{

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

        range_declaration = *__begin;
        loop_statement
    }
} 

__end 表达式在迭代之前展开。对于向量,这可能是计算 vector.data[size] 处的地址。如果循环将新元素推入向量中,则 __end 表达式不再正确。

如果您改为遍历向量的副本,则 range 语句将起作用。例如:

    for (vector<int> subset : vector<vector<int>>(subsets))
    {
        subset.push_back(current_num);
        subsets.push_back(subset);
    }

推荐阅读