Foreach 循环比传统的 for 循环使用更多的堆栈内存?

Posted

技术标签:

【中文标题】Foreach 循环比传统的 for 循环使用更多的堆栈内存?【英文标题】:Foreach loop uses more stack memory than traditional for loop? 【发布时间】:2021-12-09 18:46:50 【问题描述】:

在我的一个程序中,我使用了一个看起来与此类似的 for each 循环

for(auto component : components) 
    doSomethingWithComponent(component);

Visual Studio 抱怨这会导致函数使用的堆栈内存超过最大值,所以我将循环更改为:

for(int i = 0;i<components.size();i++) 
    doSomethingWithComponent(components[i]);

警告消失了。这是因为 for each 循环会生成循环中对象当前迭代的引用/副本吗?但如果是这样的话,我不认为带有几个整数的单个结构会消耗那么多内存吗?发生这种情况有什么原因吗?

编辑: componentsstd::vector,如果这会改变任何东西

【问题讨论】:

基于范围的 for 循环只是常规 for 循环的包装器。可能的原因可能是auto component 执行了任何组件的副本。如果您不需要副本,则应使用 auto const &amp;auto &amp; compnent/compnents[i]的类型是什么?将循环变量设为引用for (aoto&amp; component : components) 时,这是否会改变? 使用auto&amp; const 使它不再显示警告,那么这是通过复制组件而不是引用它而发生的吗?但是每次迭代的副本会发生什么?它们是被替换、销毁还是保留到循环结束> @Genjutsu 这完全取决于components的类型;如果它是 std::vector 并开启了优化,你可能会得到相同的结果,但一般来说,非基于范围的 for 循环等价物将是 for (auto iterator = std::begin(components); iterator != std::end(components); ++iterator) auto compent = *iterator; doSomethingWithComponent(component); componentsstd::vector,我会编辑我的问题 【参考方案1】:
for(auto component : components) 

这相当于拥有

auto component=components[i];

在循环的每次迭代中执行。在循环的每次迭代中,容器中的每个值都会生成一个(大部分无用的)副本。因此堆栈使用情况。

只需使用引用即可避免这种情况:

for(auto &component : components) 

如果循环不应该修改容器的内容,那就更好了:

for(const auto &component : components) 

如果由于错误而导致循环尝试修改容器中的值,您的 C++ 编译器会报错。

【讨论】:

还有一个问题,是否每个副本都保留到循环结束?还是副本的内存只是每次迭代都被一个新副本替换? 如果将auto component=components[i] 添加到手动for 循环中,最终结果将在逻辑上等价。

以上是关于Foreach 循环比传统的 for 循环使用更多的堆栈内存?的主要内容,如果未能解决你的问题,请参考以下文章

Parallel.ForEach 使用多线遍历循环

for 与forEach的区别

前端进阶知识

如何在 TypeScript 中打破 ForEach 循环

php foreach循环并在表单中添加更多按钮

使用 foreach 循环容器在表中创建新列 - 无法解决“'@P1' 附近的语法错误”错误