繁体   English   中英

"C++ 在 for 循环中声明 int"

[英]C++ Declaring int in the for loop

好久没用C++了。 我一直依靠我的 Java 编译器来进行优化。

在 C++ 中执行 for 循环的最优化方法是什么? 或者现代编译器现在都一样了吗? 在“旧时代”,情况有所不同。

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

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

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

差异在于范围。

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

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

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

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上的人比我们更聪明,并为我们处理了大部分这些简单的优化问题。 玩得开心!

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

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

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

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

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

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

for (int i = 1; ...;...)

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

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

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

C++ for 循环实际上是一个打包的 while 循环。

   for (int i=1; i<=100; i++){
   some foobar ; }

与编译器完全相同。

{ int i=1 ;
while (i<=100){
some foobar ;
i++ ; }
}

这都一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM