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 循环会生成循环中对象当前迭代的引用/副本吗?但如果是这样的话,我不认为带有几个整数的单个结构会消耗那么多内存吗?发生这种情况有什么原因吗?
编辑:
components
是 std::vector
,如果这会改变任何东西
【问题讨论】:
基于范围的 for 循环只是常规 for 循环的包装器。可能的原因可能是auto component
执行了任何组件的副本。如果您不需要副本,则应使用 auto const &
或 auto &
。
compnent
/compnents[i]
的类型是什么?将循环变量设为引用for (aoto& component : components)
时,这是否会改变?
使用auto& const
使它不再显示警告,那么这是通过复制组件而不是引用它而发生的吗?但是每次迭代的副本会发生什么?它们是被替换、销毁还是保留到循环结束>
@Genjutsu 这完全取决于components
的类型;如果它是 std::vector
并开启了优化,你可能会得到相同的结果,但一般来说,非基于范围的 for 循环等价物将是 for (auto iterator = std::begin(components); iterator != std::end(components); ++iterator) auto compent = *iterator; doSomethingWithComponent(component);
components
是std::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 循环使用更多的堆栈内存?的主要内容,如果未能解决你的问题,请参考以下文章