C++基于范围的 for 循环和元素副本

C++ range-based for loop and copy of element

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

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

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;
}

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

正如@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);
}