二元布尔运算符是否具有关联性?

fre*_*low 5 c++ boolean operators associativity

a && b && c用语言定义的(a && b) && c还是a && (b && c)

哇,杰瑞很快.加强这个问题:它真的重要吗?在a && b && c被解释为(a && b) && c或之间是否存在可观察到的差异a && (b && c)

Jer*_*fin 10

§5.14/ 1:"&&运算符从左到右分组.[...]与&,&&保证从左到右的评估:如果第一个操作数为假,则不评估第二个操作数."

至于何时或如何重要:我不确定它是否真的适用于内置类型.但是,它可能会以一种让它变得重要的方式使其超载.例如:

#include <iostream>

class A;

class M {
    int x;
public:
    M(int x) : x(x) {}
    M &operator&&(M const &r); 
    M &operator&&(A const &r); 
    friend class A;
};

class A {
    int x;
    public:
    A(int x) : x(x) {}
    A &operator&&(M const &r); 
    A &operator&&(A const &r);
    operator int() { return x;}
    friend class M;
};

M & M::operator&&(M const &r) {
    x *= r.x;
    return *this;
}

M & M::operator&&(A const &r) {
    x *= r.x;
    return *this;
}

A &A::operator&&(M const &r) {
    x += r.x;
    return *this;
}

A &A::operator&&(A const &r) {
    x += r.x;
    return *this;
}

int main() {
    A a(2), b(3);
    M c(4);

    std::cout << ((a && b) && c) << "\n";
    std::cout << (a && (b && c)) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

结果:

9
16
Run Code Online (Sandbox Code Playgroud)

警告:这只能说明它是如何能够进行无关紧要.我并不是特别建议任何人都这样做,只是表明如果你想要足够严重,你可以创造一个有所作为的情况.


izo*_*ica 5

实际上,从左到右计算表达式非常重要.这用于某些表达式中的短路.这是一个重要的案例:

vector<vector<int> > a;
if (!a.empty()  && !a[0].empty() && a[0].back() == 3) 
Run Code Online (Sandbox Code Playgroud)

我打赌你每天写几次类似的陈述.如果没有定义关联性,那么你将陷入巨大的麻烦.


zwo*_*wol 5

&&||运营商短路:如果左边的操作数确定的总体表达的结果,在右侧的操作数甚至不会被评估.

因此,数学家会将它们描述为左关联,例如
a && b && c(a && b) && c,因为数学家意味着a并且b被认为是第一个.但是,出于教学目的,改写可能是有用的a && (b && c),强调既不是 bc不会被评估是否a为假.

C中的括号仅在覆盖优先级时更改评估顺序.二者a && (b && c)
(a && b) && c会被评估a第一,然后b,再c.同样,两者的计算顺序
a + (b + c)(a + b) + c不确定.对比a + (b * c)对比(a + b) * c,这里的编译器仍然是免费评估a,b以及c以任何顺序,但括号确定乘法或加法是否首先发生.还要对比FORTRAN,其中至少在某些情况下必须首先评估带括号的表达式.