aki*_*ira 19
简短的回答:没有.
更长的答案提供一些教育见解:它完全取决于你的编译器,尽管我敢打赌,每个理智的编译器为2个表达式创建相同的代码.
示例代码:
int func_ge0(int a) {
    return a >= 0;
}   
int func_gtm1(int a) {
    return a > -1; 
}然后编译并比较生成的汇编程序代码:
% gcc -S -O2 -fomit-frame-pointer foo.cc
得出这个:
_Z8func_ge0i:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    movl    4(%esp), %eax
    notl    %eax
    shrl    $31, %eax
    ret
    .cfi_endproc
与
_Z9func_gtm1i:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    movl    4(%esp), %eax
    notl    %eax
    shrl    $31, %eax
    ret
    .cfi_endproc
(编译器:g ++ - 4.4)
结论:如果有疑问,请不要试图超越编译器,专注于算法和数据结构,基准测试和配置真正的瓶颈:检查编译器的输出.
您可以查看生成的汇编代码,这可能因架构而异,但我敢打赌,两者的结果代码都需要完全相同的周期.
并且,正如评论中所提到的 - 更好地编写最易于理解的内容,在有实际测量瓶颈时进行优化,您可以使用分析器识别这些瓶颈.
BTW:不管正确提到的,x>-1如果可能引起的问题x是unsigned.它可能被隐含地投入signed(虽然你应该得到一个警告),这会产生不正确的结果.
我最后一次回答这个问题时,我只是写了"措施",并填写了句号直到SO接受它.
该回答在几分钟内被贬低了3次,并被SO主持人删除(以及该问题的至少一个其他答案).
尽管如此,除了测量之外别无选择.
所以这是唯一可能的答案.
并且为了继续详细说明答案不仅仅是低估和删除,你需要记住,你所测量的只是:一组测量并不一定告诉你一般的东西,但只是一个特定的结果.当然,提到这些显而易见的事情可能听起来很光顾.所以,好吧,让它成为它:只是衡量.
或者,我是否应该提一下大多数处理器都有一个特殊的指令来比较零,但是那不能让你得到关于代码片段性能的任何结论?
好吧,我想我就在那里.记住:衡量.并且不要过早优化!
做在C++的比较用
int是x >= 0比更有效x > -1?
Donald Knuth,经典三卷作品"计算机编程艺术"的作者曾写过[1],
"我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源"
如何有效的 x >= 0进行比较,x > -1是最常见无关.也就是说,重点关注的可能是错误的.
它表达你想说的内容有多清楚,更为重要.您维护此代码的时间和时间通常比程序的执行时间重要得多.关注代码与其他程序员的沟通情况,即注重清晰度.
清晰度会影响正确性.如果不需要正确的话,任何代码都可以任意快速地制作.因此,正确性是最重要的,并且意味着清晰度非常重要 - 比剃须纳秒执行时间更重要......
这两个表达式不等同于wrt.清晰度和wrt.他们正确的机会.
如果x是有符号整数,则x >= 0表示完全相同x > -1.但是,如果x是无符号整数,例如类型unsigned,则x > -1意味着x > static_cast<unsigned>(-1)(通过隐式促销),这反过来意味着x > std::numeric_limits<unsigned>::max().这可能不是程序员想表达的意思!
重点是错误的另一个原因(它在微观效率上,而应该在清晰度上)是对效率的主要影响通常不是来自单个操作的时间(除了在某些情况下来自动态分配和更慢)磁盘和网络操作),但从算法效率.例如,写...
string s = "";
for( int i = 0;  i < n;  ++i ) { s = s + "-"; }
是非常低效的,因为它使用的时间与n,O(n 2),二次时间的平方成正比.
但是写作......
string s = "";
for( int i = 0;  i < n;  ++i ) { s += "-"; }
缩短与n,O(n),线性时间成比例的时间.
随着对个人操作时间的关注,人们现在可能会想到写作'-'而非"-"如此愚蠢的细节.相反,在关注清晰度的情况下,人们会专注于使代码比循环更清晰.例如,通过使用适当的string构造函数:
string s( n, '-' );
哇!
最后,第三个不让小东西流汗的原因是,通常它只是代码的一小部分,它对执行时间的贡献不成比例.通过分析代码来识别那部分(或部分)并不容易.需要进行测量,这种"在何处花费时间"测量称为剖析.
二三十年前,只需查看生成的机器代码,就可以合理地了解单个操作的效率.
例如,您可以通过在调试器中运行程序来查看机器代码,或者使用approiate选项要求编译器生成汇编语言列表.关于g ++的注意事项:该选项-masm=intel很方便告诉编译器不要生成不可编辑的AT&T语法汇编,而是生成Intel语法汇编.例如,Microsoft的汇编程序使用扩展的Intel语法.
今天,计算机的处理器更加智能.它可以不按顺序执行指令,甚至在"当前"执行点需要它们之前执行.编译器可能能够预测(通过结合从测量中收集的有效知识),但人类几乎没有机会.
因此,普通程序员的唯一办法是衡量.
测量,测量,测量!
总的来说,这包括做一件需要测量的事情,数十亿次,然后除以万亿次.
否则启动时间和取下时间将占主导地位,结果将是垃圾.
当然,如果生成的机器代码相同,那么测量不会告诉您有关相对差异的任何有用信息.然后,它只能指示测量误差有多大.因为你知道那应该是零差异.
让我们说SO答案中的理论考虑表明x >= -1会慢于x > 0.
编译器可以通过为此生成可怕的代码来击败任何这样的理论考虑x > 0,可能是由于它(不幸的是!)识别的上下文"优化"机会.
计算机的处理器同样可以使预测变得混乱.
所以无论如何你必须要衡量.
这意味着理论上的考虑并没有告诉你任何有用的东西:无论如何你都会做同样的事情,即测量.
我个人更喜欢单词"measure"作为答案.
因为这就是它归结为.
读者不仅可以自己弄清楚任何其他东西,而且还必须弄清楚无论如何都要详细说明 - 所以,试着在这里描述它真的只是措辞.
参考文献:
[1] Knuth,唐纳德.结构化编程,参见陈述,ACM Journal Computing Surveys,Vol 6,No.4,1974年12月.p.268.