if和while break之间的区别

时间:2014-01-12 20:37:35

标签: c++ performance

之间有区别吗?
if(x){

   //stuff
}

while(x){

   //stuff
   break;
}

其中一个更快吗?

8 个答案:

答案 0 :(得分:8)

逻辑上它们是一样的。编译器可能会写出相同的代码。

你应该专注于清晰的代码,而不是考虑编写混淆的代码,因为它可能会更快。

答案 1 :(得分:4)

让我们找到它:

void Test1() {
    while (GetTickCount()) {
        printf("Hello World Test1");
        break;
    }
}

void Test2() {
    if (GetTickCount()) {
        printf("Hello World Test2");
    }
}

void main() {
    Test1(); Test2();
}

使用 VC Nov 2013 CTP 编译为完全优化版本:

CPU Disasm
Address   Hex dump          Command                                  Comments
012A12A0  /$  FF15 00302A01 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
012A12A6  |.  85C0          TEST EAX,EAX
012A12A8  |.  74 0E         JZ SHORT 012A12B8
012A12AA  |.  68 8C312A01   PUSH OFFSET 012A318C                     ; ASCII "Hello World Test1"
012A12AF  |.  FF15 64302A01 CALL DWORD PTR DS:[<&MSVCR120.printf>]
012A12B5  |.  83C4 04       ADD ESP,4
012A12B8  |>  FF15 00302A01 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
012A12BE  |.  85C0          TEST EAX,EAX
012A12C0  |.  74 0E         JZ SHORT 012A12D0
012A12C2  |.  68 A0312A01   PUSH OFFSET 012A31A0                     ; ASCII "Hello World Test2"
012A12C7  |.  FF15 64302A01 CALL DWORD PTR DS:[<&MSVCR120.printf>]
012A12CD  |.  83C4 04       ADD ESP,4
012A12D0  |>  33C0          XOR EAX,EAX
012A12D2  \.  C3            RETN

如您所见,VC编译器生成相同的代码。如果禁用优化,情况就不是这样了:

<强>测试1

CPU Disasm
Address   Hex dump          Command                                  Comments
00F91630  /$  55            PUSH EBP                                 ; Playground.Test1(void)
00F91631  |.  8BEC          MOV EBP,ESP
00F91633  |>  FF15 0030F900 /CALL DWORD PTR DS:[<&KERNEL32.GetTickCo ; [KERNEL32.GetTickCount
00F91639  |.  85C0          |TEST EAX,EAX
00F9163B  |.  74 12         |JZ SHORT 00F9164F
00F9163D  |.  68 9C31F900   |PUSH OFFSET 00F9319C                    ; ASCII "Hello World Test1"
00F91642  |.  FF15 6430F900 |CALL DWORD PTR DS:[<&MSVCR120.printf>]
00F91648  |.  83C4 04       |ADD ESP,4
00F9164B  |.  EB 02         |JMP SHORT 00F9164F
00F9164D  |.^ EB E4         \JMP SHORT 00F91633
00F9164F  |>  5D            POP EBP
00F91650  \.  C3            RETN

<强>的Test2

CPU Disasm
Address   Hex dump          Command                                  Comments
00F91660  /$  55            PUSH EBP                                 ; Playground.Test2(void)
00F91661  |.  8BEC          MOV EBP,ESP
00F91663  |.  FF15 0030F900 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou ; [KERNEL32.GetTickCount
00F91669  |.  85C0          TEST EAX,EAX
00F9166B  |.  74 0E         JZ SHORT 00F9167B
00F9166D  |.  68 B031F900   PUSH OFFSET 00F931B0                     ; ASCII "Hello World Test2"
00F91672  |.  FF15 6430F900 CALL DWORD PTR DS:[<&MSVCR120.printf>]
00F91678  |.  83C4 04       ADD ESP,4
00F9167B  |>  5D            POP EBP
00F9167C  \.  C3            RETN

您可以清楚地看到它们略有不同:

  • 如果条件不满足,它们的行为完全相同(因此以相同的速度执行)

  • 如果符合条件,则在Test1我们必须再执行一次跳转(00F9164B - JMP SHORT 00F9164F

=&GT;如果在没有优化的情况下编译代码,理论上会Test2更快,因为编译器输出Test1的实数循环。


这是不成熟的优化吗?的当然!

答案 2 :(得分:2)

在汇编程序中输出代码并查看它是否与编译器相同(更可能的是,编译器将优化两个相同的机器代码,因为它们在逻辑上是等效的)。编写可读和可维护的代码几乎总是比担心这样的细节更重要。现代编译器能够优化这样的简单案例,除了以最易读的方式编写代码之外,没有什么理由可以做任何其他事情,在这种情况下,我认为将代码编写为if语句表示您的意图您的代码的其他读者远远优于while + break组合。

答案 3 :(得分:2)

它是一样的。虽然理论上while()比if

多一个jmp

答案 4 :(得分:1)

while(x){

   //stuff
   break;
}

如果您只是针对给定条件执行一次操作,则上述代码似乎是不合理的。这就是为什么在这种情况下if语句更可取的原因!至于速度差异,我真的怀疑一方面的重大优势。使用while循环代替if语句是可怕的:

if(condition)
{
    // do stuff 
}
else if(another_condition)
{
    // do stuff 
}
else
{
    // do stuff 
}

这是使用while循环的等价物:

while(condition)
{
    // do stuff
    break;
}
while(!condition && another_condition)
{
    // do stuff
    break;
}
while(!condition && !another_condition)
{
    // do stuff
    break;
}

让您的团队受宠,让您的代码可读: - )

答案 5 :(得分:1)

他们有不同的目的。

if是一个选择陈述

while是一个迭代语句。

并且应该根据他们的目的使用它们。

答案 6 :(得分:1)

如果在第一次迭代时断开while循环,则while循环用作if语句。

但是你不应该为此目的使用while循环,因为它的目的是循环。

答案 7 :(得分:-1)

因此,以下内容可能会提供相同的内容,因为for-C由C预处理器修改为一段时间。其他人对清晰度的看法虽然......

for(;x;){
  //stuff
  break;
}