C ++中bool值的逻辑“或”效率

时间:2013-09-05 21:02:29

标签: c++ boolean bitwise-operators

bool x = false, y = false, z = true;

if(x || y || z){}

or

if(x | y | z){}

第二个if语句是否对所有布尔值执行了一些“或”操作?把它们视为有字节吗? ex)(0000 | 0000 | 0001)= true ...

或者它是否像Java一样在布尔值上,它会评估表达式中的每一个bool,即使第一个是真的吗?

我想知道位运算符如何处理bool值。它等同于整数按位运算吗?

2 个答案:

答案 0 :(得分:8)

效率取决于,逻辑或运算符||是短路运算符 意味着如果您的示例中的x为真,则不会评估yz。 如果它是合乎逻辑的&&,那么如果x为false,则不会测试yz。 重要的是要注意,此操作不作为指令存在 这意味着你必须使用测试和跳转指令。这意味着分支,这会减慢事情的速度。由于现代CPU是流水线的。

但真正的答案是,这与其他许多问题有关,因为短路操作的好处有时会超过成本。

在下面非常简单的示例中,您可以看到按位或|是优越的。

#include <iostream>


bool test1(bool a, bool b, bool c)
{
    return a | b | c;
}

bool test2(bool a, bool b, bool c)
{
    return a || b || c;
}

int main()
{
  bool a = true;
  bool b = false;
  bool c = true;
  test1(a,b,c);
  test2(a,b,c);
  return 0;
}

以下是gcc-4.8使用-O3生成的英特尔风格的汇编列表:
test1汇编:

_Z5test1bbb:
.LFB1264:
    .cfi_startproc
    mov eax, edx
    or  eax, esi
    or  eax, edi
    ret
    .cfi_endproc

test2议会:

_Z5test2bbb:
.LFB1265:
    .cfi_startproc
    test    dil, dil
    jne .L6
    test    sil, sil
    mov eax, edx
    jne .L6
    rep; ret
    .p2align 4,,10
    .p2align 3
.L6:
    mov eax, 1
    ret
    .cfi_endproc

你可以看到它有分支指令,这会弄乱管道。

但有时短路是值得的,例如

return x && deep_recursion_function();

<强>声明:

我总是在bools上使用逻辑运算符。除非性能真的很重要,或者像test1test2那样简单,但有很多bool。 在任何一种情况下,首先要确认你确实得到了改进。

答案 1 :(得分:3)

第二个是java |整数,有点或。由于C最初没有布尔类型,if语句将任何非零值读为true,因此您可以将其用作,但使用短路运算符通常更有效||相反,尤其是在调用返回条件的函数时。

我还想指出,短路可让您检查不安全的情况,例如if(myptr == NULL || myptr->struct_member < 0) return -1;,同时使用按位,或者当myptr 为null时会出现段错误。