C ++在for循环中声明int

时间:2010-02-12 22:09:29

标签: c++

暂时没有使用过C ++。我一直依靠我的Java编译器来进行优化。

在C ++中进行for循环的最佳方法是什么?或者现在与现代编译器完全相同?在“旧时代”中存在差异。

for (int i=1; i<=100; i++)

OR

int i;
for (i=1; i<=100; i++)

OR

int i = 1;
for ( ; i<=100; i++)

在C中是否相同?

修改 好的,所以压倒性的共识是使用第一种情况,如果需要,让编译器优化它。

9 个答案:

答案 0 :(得分:12)

我会说像这样的琐碎事情可能是由编译器优化的,你不应该担心它们。第一个选项是最易读的,所以你应该使用它。

编辑:添加其他答案所说的,还有不同之处在于,如果在循环初始化程序中声明变量,它将在循环结束后停止存在。

答案 1 :(得分:9)

区别在于范围。

for(int i = 1; i <= 100; ++i)

通常是优选的,因为 i 的范围仅限于for循环。如果在for循环之前声明它,那么它在for循环结束后继续存在并且可能与其他变量冲突。如果你只是在for循环中使用它,那么就没有理由让它存在的时间超过这个。

答案 2 :(得分:5)

让我们说原始海报有一个他们真正想要优化的循环 - 每一条指令都被计算在内。我们怎样才能 - 凭经验 - 弄清楚他的问题的答案?

gcc至少有一个有用的,如果不常用的开关,'-S'。它转储.c文件的汇编代码版本,可用于回答OP姿势等问题。我写了一个简单的程序:

int main( )
{
    int sum = 0;

    for(int i=1;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

并运行:gcc -O0 -std=c99 -S main.c,创建主程序的汇编版本。这是main.s的内容(删除了一些绒毛):

    movl    $0, -8(%rbp)
    movl    $1, -4(%rbp)
    jmp     .L2
.L3:
    movl    -4(%rbp), %eax
    addl    %eax, -8(%rbp)
    addl    $1, -4(%rbp)
.L2:
    cmpl    $10, -4(%rbp)
    jle     .L3

您无需成为装配专家即可了解正在发生的事情。 movl移动值,addl添加东西,cmpl比较和jle代表'jump if than',$是常量。它将0加载到某个东西 - 必须是'sum',1加入其他东西 - 啊,'我'!跳转到L2我们比较10,跳转到L3进行添加。再次进入L2进行比较。整齐!一个for循环。

将程序更改为:

int main( )
{
    int sum = 0;
    int i=1;
    for( ;i<=10;++i)
    {
        sum = sum + i;
    }
    return sum;
}

重新运行gcc和生成的组件将非常相似。有一些东西正在记录行号,所以它们不会完全相同,但程序集最终是相同的。与最后一个案例相同的结果。因此,即使没有优化,代码也差不多。

为了好玩,请使用'-O3'而不是'-O0'重新运行gcc以启用优化并查看.s文件。

main:
movl    $55, %eax
ret

gcc不仅弄清楚我们正在做一个for循环,而且还意识到它是在编译时为我们循环运行了一段时间,将'i'和'sum'清除并硬编码回答--55!这很快 - 虽然有点做作。

故事的道德?花时间确保您的代码干净且设计精良。可读性和可维护性代码。生活在山露和cheetos上的人比我们更聪明,并为我们处理了大部分这些简单的优化问题。玩得开心!

答案 3 :(得分:4)

它是一样的。编译器会将这些优化为同样的东西。

即使它们不相同,与循环的实际主体相比的差异也可以忽略不计。你不应该担心像这样的微优化。除非你进行性能分析,看看它是否确实有所作为,否则你不应该进行微观优化。

答案 4 :(得分:3)

速度方面也是如此。如果您以后没有使用i,编译器将进行优化。

就风格而言 - 我将定义放在循环结构中,因为它可以降低您在以后定义另一个时会发生冲突的风险。

答案 5 :(得分:1)

不要担心微优化,让编译器去做。选择最具可读性的。请注意,在for初始化语句中声明变量会将变量范围限定为for语句(C ++ 03 § 6.5.3 1),尽管编译器的确切行为可能会有所不同(有些可让您选择) )。如果循环外的代码使用变量,则在循环外声明它。如果变量对循环是真正的局部变量,则在初始化器中声明它。

答案 6 :(得分:1)

已经提到两者之间的主要区别在于范围。确保您了解编译器如何处理声明为

的int的范围
for (int i = 1; ...;...)

我知道在使用MSVC ++ 6时,我仍然在循环之外的范围内,就好像它是在循环之前声明的那样。这种行为与VS2005不同,我必须检查,但我认为我使用的最后一个版本的gcc。在这两个编译器中,该变量仅在循环内的范围内。

答案 7 :(得分:1)

for(int i = 1; i <= 100; ++i)

这是最容易阅读的,但ANSI C / C89除外,它是无效的。

答案 8 :(得分:-1)

一切都是一样。