"和","&&"之间的C ++差异和" bitand"

时间:2018-01-06 15:47:06

标签: c++ performance optimization

我想知道C ++中的速度或性能是否存在差异:

AND操作:&&, and, bitand

OR操作:||, or, bitor

或者所有人的表现相同?

2 个答案:

答案 0 :(得分:4)

在详细说明之前,&&and是等效的,&bitand||or以及|bitor。有关详细信息,请参阅cppreference.com

它们之间肯定存在差异,所以让我们更详细地看一下它们:

  • &&||逻辑运算符。他们的结果是truefalse,没有别的 如果至少有一个操作数(||)或两个操作数(&&)不是false,则结果为true,否则为false。< / p>

  • &|按位运算符。它们独立地操作每一个操作数 这主要用于对数字进行位操作,比如将数字的最低3位设置为0(考虑它们的二进制表示):

    int result1 = number & 0b111;
    // or to set the 3 lowermost bits to 1
    int result2 = number | 0b111;
    

您可能知道,对于条件语句,C ++中的每个数字都可以解释为布尔值,更具体地说,0是false,其他所有数字都是true。这可能会导致一些混淆,如下例所示:

int a = 1;
int b = 2;
if (a && b) {
    std::cout << "a && b\n";
}
if (a & b) {
    std::cout << "a & b\n";
}

这将只输出a && b,因为a & b为0,因此false,即使ab都不是false

简而言之,对于逻辑操作使用&&||,对于数字上的按位操作使用&|,但请注意副作用:

除了不同的使用范围外,这些运算符之间还存在另一个差异,即逻辑运算符(&&||)的强制短路评估。这意味着如果我们已经通过计算第一个操作数来知道表达式的结果,那么第二个操作数就不能进行评估。这意味着以下两段代码是等效的:

    bool result = is_this_true() && is_that_true();
    // equivalent:
    bool result;
    if (is_this_true()) {
        result = is_that_true();
    } else {
        result = false;
    }

逻辑或运算符也是如此:

    bool result = is_this_true() || is_that_true();
    // equivalent:
    bool result;
    if (is_this_true()) {
        result = true;
    } else {
        result = is_that_true();
    }

这是因为

  1. 如果&&的其中一个操作数为false,则结果始终为false
  2. 如果||的其中一个操作数为true,则结果始终为true
  3. 与按位运算符相比,这肯定会对性能产生影响,基本上有两种不同的方式:

    1. 如果is_that_true()的评估需要花费很多时间,那么短路评估可能会节省您在结果短路的情况下的时间。

    2. 如果对is_this_true()is_that_true()的评估都非常快但有副作用,编译器无法摆脱,那么由等效if引入的附加分支声明可能涉及一个小的性能损失(更多细节,阅读分支错误预测)。但是,在大多数情况下,这种性能差异非常小,除非对这些逻辑运算符的评估是您的性能瓶颈(再次,这应该是非常不可能),否则您不应该担心它。

    3. 如果您想了解更多信息,已经有几个答案详细说明了短路评估的效果,例如,请参阅 Is short-circuiting logical operators mandated? And evaluation order?

答案 1 :(得分:1)

  

或者所有人的表现相同?

这是一个苹果/橘子问题。 andbitand执行不同的工作。

示例:

bool both_nonzero(int x, int y)
{
    return x and y;
}

bool have_corresponding_bits(int x, int y)
{
    return bool(x bitand y);
}

相应的汇编程序(gcc-x86_64 -O3):

both_nonzero(int, int):
        test    edi, edi
        setne   al
        test    esi, esi
        setne   dl
        and     eax, edx
        ret

have_corresponding_bits(int, int):
        test    edi, esi
        setne   al
        ret

正如您所看到的,第二个功能需要更少的指令,但从CPU的角度来看,它执行的任务更简单(按位操作是CPU的基础和黄油)生活的工作)。