如果和同时中断之间的区别
Difference between if and while break
两者之间有区别吗
if(x){
//stuff
}
和
while(x){
//stuff
break;
}
?
其中一个更快吗?
从逻辑上讲,它们是相同的。编译器可能会写出相同的代码。
您应该专注于代码的清晰度,而不是考虑编写混淆代码,希望它可能会更快。
让我们找出答案:
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
测试2
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
)
如果代码在没有 optimizatzion 的情况下编译,=> Test2
理论上会更快,因为编译器输出了一个 Test1
的真实循环。
这是过早的优化吗?绝对!
在汇编器中输出代码,看看它是否与您的编译器相同(您的编译器很可能会将两者优化为相同的机器代码,因为它们在逻辑上是等效的)。几乎总是,编写可读和可维护的代码比担心诸如此类的细节更重要。由于现代编译器能够优化出像这样的简单情况,除了以最易读的方式编写代码之外,几乎没有理由做任何事情,在这种情况下,我认为将代码编写为if
语句向代码的其他读者表明您的意图远比 while
+ break
组合更好。
虽然理论上 while() 比 if
它们的目的只是不同。
if
是选择语句
while
是一个迭代语句。
它们应该根据其目的使用。
如果在第一次迭代时中断 while 循环,则 while 循环充当 if 语句。
但是你永远不应该为此目的使用 while 循环,因为它的目的是循环。
while(x){
//stuff
break;
}
如果您只打算对给定条件执行一次操作,上面的代码似乎不合理。这就是为什么在这种情况下,如果语句更可取!至于速度差异,我真的怀疑一个比另一个有什么显着优势。使用 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;
}
帮你的团队一个忙,让你的代码可读:-)
以下内容可能会给出相同的结果,因为 for 被 C 预处理器修改为一段时间。不过,其他人对清晰度的看法...
for(;x;){
//stuff
break;
}
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 这 4 个 lambda 表达式之间有什么区别?
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- (double) 和 double() 之间的区别
- & 和 * 之间的区别
- std::is_convertible 和 std::convertible_to 之间的区别(在实践中)?
- 析构函数和'delete'之间的区别
- 在 typedef 内部使用 const 关键字和在 typedef 外部使用 const 关键字之间有区别吗?
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 函数签名与调用的函数不匹配,常量字符[]和字符*之间的区别?
- OpenMP #pragma omp for v/s #pragma omp parallel for 之间的区别?
- S() 与 S{} 之间的区别?