1

循环外的变量

int number = 0;
for(int i = 0; i < 10000; i++){
     number = 3 * i;
     printf("%d",number);
}

或循环内的变量

for(int i = 0; i < 10000; i++){
     int number = 3 * i;
     printf("%d",number);
}

推荐哪一款,哪一款性能更好?

编辑:

这只是展示我的意思的一个例子,我只想知道在循环内和循环外定义一个变量是否意味着相同的事情,或者有区别。

4

5 回答 5

6

是时候尽早学习一些东西了:面对 printf,您可以对此类内容进行的任何优化都将无关紧要。

Printf 会非常非常慢。你可以将数学增加五倍,并且没有可测量的速度下降。这只是打印到终端的性质。

至于您编辑过的问题,在循环中或输出中定义它没有区别。设想

for (i = 0; i < 500; i++) {
  int a = i * 3;
}

int forloop::a; // This doesn't work, the idea is to show it just changes the scope
for (i = 0; i < 500; i++) {
  a = i * 3;
}

它们将产生相同的代码,除非您开始需要在定义它的循环之外使用该变量,因为它是在循环的本地范围内定义的。所以......更像这样:

int forloop::a;    // Still not valid code, just trying to show an explanation
namespace forloop {
for (i = 0; i < 500; i++) {
  a = i * 3;
}
} // namespace forloop

如果不清楚,请告诉我,我会更详细地介绍或以不同方式解释。

于 2012-04-03T22:37:48.397 回答
2

您确实有一个 C++ 标记,并且您在问题中提到了“声明字符串”。因此可能存在性能差异(是的, printf 可能会淹没它)。声明一个非简单变量意味着调用一个构造函数,这可能意味着大量的工作。在这种情况下,在循环内声明它可能会在看似无辜的声明中隐藏重要的工作。

一般来说,答案是,如果你真的关心性能——并且只将示例代码视为两个地方之间声明变量的差异的示例——那么对于非简单变量,最好在循环之外声明它,除非语义在每次迭代时都需要一个新版本的临时变量。

如果性能是一个问题,可能还有很多其他地方首先要查看,但一个考虑因素总是将循环不变量移出循环,特别是如果您更容易判断它是不变的,而不是编译器。看起来像声明的东西,在 C++ 中就属于这一类。

如果,对于(愚蠢的)例子,你有

int k = 43;
for ( int i = 0; i < N; ++i )
    {
    int j = 17 + k; // k was previously defined outside the loop, but doesn't change in it
    l = j * j; // l was also declared outside the loop
    }

任何优秀的优化编译器都可以识别出 k 是常量,并且 j 总是被分配 60,而 l 被分配了 3600 N 次,并且可以简单地删除循环并用对 l 的单个分配替换。这里 k 和 j 都是循环不变量。

但是一个不太好的编译器可能会错过该链中的一个链接,并最终创建循环。

当你有

 Foo k( 43 );  // a class that takes an int argument to its constructor
 for( int i = 0; i < N; ++i )
    {
    Bar j( k ); // a Bar takes an int argument, adds 17 and stores it.
    l = j.squared();
    }

相同的不变量。如果不查看 bar 的工作原理,就不容易检测到;如果构造函数和 squared 方法不是内联的,我们只是让它变慢了。

于 2012-04-03T23:05:24.023 回答
2

不要一开始就用性能来打扰你:在一切之前让它安全。

我只想引用Scott Meyers (Effective C++)来表达您的担忧: “尽可能推迟声明”。因此,第二种模式更安全。

例子:

int j = 0;
for(int i = 0; i < 10000; i++){
    j = 3 * i;
    printf("%d",j);
}
...
// Use of j out of control!!!
int k = j * 5;

现在使用第二种模式:

for(int i = 0; i < 10000; i++){
    int j = 3 * i;
    printf("%d",j);
}
...
// j not declared at this point.
// You get informed of the mistake at compile time, which is far much better.
int k = j * 5; 
于 2012-04-03T22:53:32.457 回答
0

在这种情况下, printf("%d", i * 3) 将比定义变量更好。

于 2012-04-03T22:34:02.000 回答
0

要回答您的问题而不是吹毛求疵:

两种变体之间的区别在于,您number在不同的“变量环境”中声明变量——我的意思是范围发生了变化。变量环境由您的花括号给出{ ... }。每次像这样打开一个新的大括号{ ... { ... } ... }时,都会在旧的大括号中声明一个新的变量环境,这意味着,如果你numbers这样声明:

{ ... { int numbers; ... } ... }

此变量仅在最内部的环境中可见或存在。所以

{ ... { int numbers; ... } ... do_something(numbers); ... }

将给出编译器错误。

对于您对性能的担忧:这两种变体都没有更好的性能。大多数(如果不是所有)编译器都会给出相同的程序集。

于 2012-04-03T22:50:18.173 回答