【问题标题】:Does writing boolean conditions "in full" compromise performance?“完整”编写布尔条件是否会影响性能?
【发布时间】:2014-07-21 12:42:52
【问题描述】:

为了可读性,我喜欢在 C/C++ 中“完整地”编写布尔条件,例如:

if (foo == true) 代替 if (foo)if (foo == false) 代替 if (!foo)

这会影响性能吗?

【问题讨论】:

  • 运行程序的性能?还是可怜的维护程序员试图通过无关的噪音来读取逻辑?
  • 为了可读性而使用的样式会损害可读性。
  • 即使是用英语,明确地说明比较通常会更清楚:“如果___是真的,那么我要去___。”可读性是旁观者的眼睛,通常是宗教辩论的主题。 OP 并没有寻求帮助来决定什么更具可读性,只是他/她喜欢的风格是否有任何性能成本。
  • 问题是:你有一个bool类型的值。如果你坚持将bool类型的值与truefalse进行比较,那么你的问题是foo == true也是bool类型的值,所以你实际上需要(foo == true) == true。除了那也是bool,等等,无穷无尽。
  • @Caleb 这就是为什么上面是 cmets,而不是答案。 (当我看到类似if ( foo == bool ) 的内容时,它会读到类似“作者不理解布尔类型或一般类型系统的概念,所以要小心他写的任何东西。)

标签: c++ c performance readability


【解决方案1】:

假设 foo 是一个布尔值,它不是。编译器可以对其进行简单优化。

但是,如果 foo 是一个类,则情况可能并非如此,它可以重载运算符以执行任何操作。

【讨论】:

  • 现在会很有趣。用不相关的语义重载 operator!operator==(bool)。 (但我推测他说的是foo 类型的bool。)
  • 谢谢。我很想知道如果foo 是布尔值,为什么编译器需要优化?
  • @JamesKanze:所有愿意抛弃所有惯例和常识的人都会有很多乐趣......
  • @mga James 在他的评论中有解释。简单来说,一个if语句有一个隐含的== true,所以if (foo == true)实际上就像if ((foo == true) == true)
  • @JamesKanze 也许有人希望! 不是不重要,而是重要!所以!foo 让foo 变得更大。
【解决方案2】:

就直接C而言,这两种形式可能产生不同的机器码,可能影响性能。性能差异是否重要将取决于代码在做什么以及您的性能要求是什么。

在 SLES 10 上使用 gcc 4.1.2,if ( foo == false )if ( !foo ) 的机器代码略有不同;给出以下源代码:

if ( foo == false )
{
  printf( "foo is false\n" );
}

if ( !foo )
{
  printf( "foo is 0\n" );
}

我得到以下机器代码 (gcc -S -std=c99 -pedantic -Wall -Werror):

        movb    $0, -1(%rbp)      ;; foo = false
        cmpb    $0, -1(%rbp)      ;; if ( foo == false )
        jne     .L6               ;; {
        movl    $.LC2, %edi       ;;   
        call    puts              ;;    printf( "foo is false\n" );
.L6:                              ;; }
        movzbl  -1(%rbp), %eax    ;; if ( !foo )
        xorl    $1, %eax   
        testb   %al, %al
        je      .L8               ;; {
        movl    $.LC3, %edi       ;;   
        call    puts              ;;    printf( "foo is 0\n" );
.L8:                              ;; }
        movl    $0, %eax

对于这个特定的平台、编译器、代码和一组编译器选项if (!foo) 最终可能会比if ( foo == false ) 慢一点1

现在,对于真正的问题:这种性能差异(如果存在的话)重要吗?对于这个特定的程序,绝对不是;测试在程序的整个生命周期中发生一次,执行 I/O 所花费的时间将大大超过执行测试所花费的时间。在另一个程序中,该测试在 CPU 绑定的紧密循环中执行数千或数百万次,那么它可能非常重要。

代码可读性first; if ( foo )if ( !foo ) 形式对于简单的布尔测试来说往往是惯用的,这也是大多数 C 和 C++ 程序员期望看到的。话虽如此,写if ( foo == TRUE )if ( foo == FALSE ) 绝对没有错,如果您觉得它更好地传达了代码的意图(或者如果您决定将TRUE 定义为0 和FALSE 定义为1,无论出于何种原因) .

但是不要根据表现做出决定除非

  1. 您没有达到硬性能要求;
  2. 您已经适当地优化了您的算法和数据结构;和
  3. 分析显示特定语句是剩余的瓶颈。


1. 或不;这取决于xorltestb 需要多少个周期与cmpb 以及直接访问寄存器%eax 比计算-1(%rbp) 并访问结果位置快多少;据我所知,这是洗头。

【讨论】:

    【解决方案3】:
    if(foo == true)
    

    即使使用邪恶的重载,它也可以具有与更惯用的重载不同的语义和性能特征,因为它不那么冗长

    if( ! foo)
    

    ,使用健全的类型和相当高效的编译器,它应该产生完全相同的本机指令。

    如果您允许恶意超载,那么无论如何,所有的赌注都会失败,并且您会遇到预期的麻烦。

    尽管如此,以上并不是总是添加显式比较的愚蠢行为的典型示例。
    这将是:

    if(foo)
    if(foo == true)
    if((foo == true) == true)
    // ...
    

    缺点是:

    • 不必要的冗长,什么都不澄清。
    • 有忘记=-sign 的危险,因此尝试分配值。
    • “澄清”到什么程度才算清楚?
    • 如果不使用布尔常量的关键字,而是使用底层的 0 和 1,这样做有可能会比较等于 1,而需要不等于 0。

    请注意,在 C、C++ 和一些相关语言中,指针、整数(包括字符类型)和大多数用户定义的类型也是如此。

    【讨论】:

      【解决方案4】:

      假设 foo 是一个布尔值,它不是。编译器可以对其进行简单优化。

      但是,如果 foo 是一个类,则情况可能并非如此,它可以重载运算符以执行任何操作。

      【讨论】:

      • 你为什么要逐字复制@neilkirk的回答?
      • 复制自@Neil-Kirk。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      相关资源
      最近更新 更多