假设我们有一个迭代多次的循环:
for (int i=0; i < 1000000; ++i) {
int s = 100;
s += i;
cout << s;
}
我们只在循环体内使用s
,所以理想情况下我们要在那里声明它,这样就不会污染封闭的命名空间。
我想知道是否有任何不利之处。例如,它是否会产生性能成本,因为程序会在每次迭代时重新声明s
?
答案 0 :(得分:7)
概念上该变量是在每次迭代时构造和销毁的。
但是它会影响性能吗?那么,你可以查看你的案例right here。删除第7行的int
以在loop-local和function-local变量之间切换
结论:没有任何区别。装配是一样的!
因此,只需使用代码中有意义的内容即可。如果每次迭代需要一个对象,则每个对象生成一个对象。优化器比您想象的更聪明。如果这还不够,你会回过头来分析数据并仔细调整,而不是广泛的指导。
答案 1 :(得分:2)
是。在循环内声明变量将导致在每次迭代时对其进行解构和重构。对于小循环和简单数据类型,这可能不太明显,编译器无论如何都会对其进行优化,但是在处理复杂对象和大循环时,最好将变量声明为外部。
如果循环的变量使用太多内存,则可以将循环和声明括在大括号中,从而导致在退出后删除在大括号内分配的所有变量。大多数情况下,这样的微优化并不重要,但如果您使用复杂的类等,只需使用外部初始化变量并每次重置它。
通常,声明太多变量并不是一个好主意,它会使您的代码难以阅读并增加内存使用量。如果可以,请不要在不需要时声明变量。例如,您的示例可以简化为for(int i = 0;i<1000000;i++)cout<<i+100;
。如果这样的优化是可能的并且它们不会使您的代码难以阅读,请使用它们。
答案 2 :(得分:1)
销毁int是noop。变量不再存在,但不需要运行运行时代码。
对不再存在的变量的引用或指针具有未定义的行为。在初始化之前,新创建的局部变量具有未定义状态。因此,简单地将旧变量重新用于新变量是合法的,编译器不必证明没有这样的优秀引用。
在这种情况下,如果它可以证明该值是常量100
,它甚至可以跳过除第一次初始化之外的所有内容。它可以做这个初始化&#34;早期&#34;因为没有确定的方法可以及早发现它。在这种情况下,它很容易,大多数编译器都可以轻松完成;在更复杂的情况下,不那么重要。如果你标记它const
,编译器不再需要证明它是未经修改的,而是可以假设它!
存在许多C ++未定义的区域,以便使某些优化变得容易。
现在,如果你有一些更复杂的东西,比如vector<int>{1,2,3,4,5}
,破坏和创造就变得不那么吵闹了。仍然可以提升&#39;变量不在循环中,但对编译器来说要困难得多。这是因为动态分配有时难以优化。