C++ if (flag==0) 或 if (0==flag) 哪个会执行得更快?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4624536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Which one will execute faster, if (flag==0) or if (0==flag)?
提问by mr_eclair
Interview question: Which one will execute faster, if (flag==0)
or if (0==flag)
? Why?
面试问题:哪个会执行得更快,if (flag==0)
还是if (0==flag)
?为什么?
回答by Matthieu M.
I haven't seen any correct answer yet (and there are already some) caveat: Nawaz did point out the user-defined trap. And I regret my hastily cast upvote on "stupidest question" because it seems that many did not get it right and it gives room for a nice discussion on compiler optimization :)
我还没有看到任何正确的答案(并且已经有一些)警告:Nawaz 确实指出了 user-defined trap。我很遗憾我仓促地对“最愚蠢的问题”投了赞成票,因为似乎很多人没有做对,这为关于编译器优化的讨论提供了空间:)
The answer is:
答案是:
What is
flag
's type?
什么是
flag
类型?
In the case where flag
actually is a user-defined type. Then it depends on which overload of operator==
is selected. Of course it can seem stupid that they would not be symmetric, but it's certainly allowed, and I have seen other abuses already.
在flag
实际上是用户定义类型的情况下。那么这取决于选择了哪个重载operator==
。当然,它们不对称似乎很愚蠢,但这当然是允许的,而且我已经看到了其他滥用行为。
If flag
is a built-in, then both should take the same speed.
如果flag
是内置的,那么两者应该采用相同的速度。
From the Wikipedia articleon x86
, I'd bet for a Jxx
instruction for the if
statement: perhaps a JNZ
(Jump if Not Zero) or some equivalent.
从Wikipedia 上的文章中x86
,我敢打赌Jxx
该if
语句的说明:也许是JNZ
(如果不是零则跳转)或某种等价物。
I'd doubt the compiler misses such an obvious optimization, even with optimizations turned off. This is the type of things for which Peephole Optimizationis designed for.
我怀疑编译器会错过如此明显的优化,即使优化关闭。这是窥视孔优化设计的对象类型。
EDIT:Sprang up again, so let's add some assembly (LLVM 2.7 IR)
编辑:再次出现,所以让我们添加一些程序集(LLVM 2.7 IR)
int regular(int c) {
if (c == 0) { return 0; }
return 1;
}
int yoda(int c) {
if (0 == c) { return 0; }
return 1;
}
define i32 @regular(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
define i32 @yoda(i32 %c) nounwind readnone {
entry:
%not. = icmp ne i32 %c, 0 ; <i1> [#uses=1]
%.0 = zext i1 %not. to i32 ; <i32> [#uses=1]
ret i32 %.0
}
Even if one does not know how to read the IR, I think it is self explanatory.
即使一个人不知道如何阅读 IR,我认为它是不言自明的。
回答by Nawaz
There will be no difference in your versions.
您的版本不会有任何差异。
I'm assuming that the type
of flag is not user-defined type, rather it's some built-in type. Enum is exception!. You can treat enum as if it's built-in. In fact, it' values are one of built-in types!
我假设type
of 标志不是用户定义的类型,而是某种内置类型。枚举是个例外!. 您可以将枚举视为内置的。事实上,它的值是内置类型之一!
In case, if it's user-defined type (except enum
), then the answer entirely depends on how you've overloaded the operator ==
. Note that you've to overload ==
by defining two functions, one for each of your versions!
万一,如果它是用户定义的类型(除了enum
),那么答案完全取决于您如何重载 operator ==
。请注意,您必须==
通过定义两个函数来重载,每个版本一个!
回答by skc
Same code for amd64 with GCC 4.1.2:
amd64 与 GCC 4.1.2 的相同代码:
.loc 1 4 0 # int f = argc;
movl -20(%rbp), %eax
movl %eax, -4(%rbp)
.loc 1 6 0 # if( f == 0 ) {
cmpl if (flag = 0) // typo here
{
// code never executes
}
if (0 = flag) // typo and syntactic error -> compiler complains
{
// ...
}
, -4(%rbp)
jne .L2
.loc 1 7 0 # return 0;
movl struct sInt
{
sInt( int i ) : wrappedInt(i)
{
std::cout << "ctor called" << std::endl;
}
operator int()
{
std::cout << "operator int()" << std::endl;
return wrappedInt;
}
bool operator==(int nComp)
{
std::cout << "bool operator==(int nComp)" << std::endl;
return (nComp == wrappedInt);
}
int wrappedInt;
};
int
_tmain(int argc, _TCHAR* argv[])
{
sInt s(0);
//in this case this will probably be faster
if ( 0 == s )
{
std::cout << "equal" << std::endl;
}
if ( s == 0 )
{
std::cout << "equal" << std::endl;
}
}
, -36(%rbp)
jmp .L4
.loc 1 8 0 # }
.L2:
.loc 1 10 0 # if( 0 == f ) {
cmpl if(flag=0) // <--- typo: = instead of ==; flag is now set to 0
{
// this is never executed
}
if(0=flag) // <--- compiler error, cannot assign value to literal
{
}
, -4(%rbp)
jne .L5
.loc 1 11 0 # return 1;
movl , -36(%rbp)
jmp .L4
.loc 1 12 0 # }
.L5:
.loc 1 14 0 # return 2;
movl , -36(%rbp)
.L4:
movl -36(%rbp), %eax
.loc 1 15 0 # }
leave
ret
回答by Linus Kleen
There is absolutely no difference.
绝对没有区别。
You might gain points in answering that interview question by referring to the elimination of assignment/comparison typos, though:
不过,通过参考消除作业/比较拼写错误,您可能会在回答该面试问题时获得分数:
if(flag=0) // <--- warning: assignment in conditional expression
{
}
While it's true, that e.g. a C-compiler does warn in case of the former (flag = 0
), there are no such warnings in PHP, Perl or Javascript or <insert language here>
.
虽然确实如此,例如 C 编译器确实会在前者 ( flag = 0
) 的情况下发出警告,但在 PHP、Perl 或 Javascript 或<insert language here>
.
回答by Jon
There will be absolutely no difference speed-wise. Why should there be?
速度方面绝对没有区别。为什么应该有?
回答by ds27680
Well there is a difference when flag is a user defined type
当 flag 是用户定义的类型时会有区别
##代码##In the first case (0==s) the conversion operator is called and then the returned result is compared to 0. In the second case the == operator is called.
在第一种情况下 (0==s) 调用转换运算符,然后将返回的结果与 0 进行比较。在第二种情况下调用 == 运算符。
回答by Elzo Valugi
When in doubt benchmark it and learn the truth.
如有疑问,请对其进行基准测试并了解真相。
回答by Matteo Italia
They should be exactly the same in terms of speed.
它们在速度方面应该完全相同。
Notice however that some people use to put the constant on the left in equality comparisons (the so-called "Yoda conditionals") to avoid all the errors that may arise if you write =
(assignment operator) instead of ==
(equality comparison operator); since assigning to a literal triggers a compilation error, this kind of mistake is avoided.
但是请注意,有些人习惯于将常量放在等式比较(所谓的“Yoda 条件”)的左侧,以避免在您编写=
(赋值运算符)而不是==
(等式比较运算符)时可能出现的所有错误;由于分配给文字会触发编译错误,因此可以避免这种错误。
On the other hand, most people find "Yoda conditionals" weird-looking and annoying, especially since the class of errors they prevent can be spotted also by using adequate compiler warnings.
另一方面,大多数人发现“Yoda 条件”看起来很奇怪而且很烦人,特别是因为它们防止的错误类别也可以通过使用足够的编译器警告来发现。
##代码##回答by darioo
As others have said, there is no difference.
正如其他人所说,没有区别。
0
has to be evaluated. flag
has to be evaluated. This process takes the same time, no matter which side they're placed.
0
必须被评估。flag
必须被评估。无论放置在哪一边,此过程都需要相同的时间。
The right answer would be: they're both the same speed.
正确答案是:它们的速度相同。
Even the expressions if(flag==0)
and if(0==flag)
have the same amount of characters! If one of them was written as if(flag== 0)
, then the compiler would have one extra space to parse, so you would have a legitimate reason at pointing out compile time.
连表情if(flag==0)
和if(0==flag)
字符数都一样!如果其中之一被编写为if(flag== 0)
,那么编译器将有一个额外的空间来解析,因此您将有合理的理由指出编译时间。
But since there is no such thing, there is absolutely no reason why one should be faster than other. If there is a reason, then the compiler is doing some very, very strange things to generated code...
但既然没有这样的东西,绝对没有理由为什么一个人应该比另一个人快。如果有一个原因,那么编译器正在对生成的代码做一些非常非常奇怪的事情......
回答by davka
Well, I am agreeing completely with all said in the comments to the OP, for the exercise sake:
好吧,为了练习,我完全同意在对 OP 的评论中所说的所有内容:
If the compiler is not clever enough (indeed you should not use it) or the optimization is disabled, x == 0
could compile to a native assembly jump if zero
instruction, while 0 == x
could be a more generic (and costly) comparison of numeric values.
如果编译器不够聪明(实际上你不应该使用它)或者优化被禁用,x == 0
可以编译为本机汇编jump if zero
指令,同时0 == x
可能是更通用(和成本更高)的数值比较。
Still, I wouldn't like to work for a boss who thinks in these terms...
尽管如此,我还是不想为一个以这些方式思考的老板工作......