C++:*(乘法)运算符的关联性不是从左到右

Mar*_*aux 2 c++ operator-overloading associativity operator-keyword

在完成学校作业时,我们不得不对操作员重载和模板做些什么.一切都很酷.我写:

template<class T>
class Multiplication : public Expression<T>
{
private:
        typename std::shared_ptr<Expression<T> > l, r;

public:
        Multiplication(typename std::shared_ptr<Expression<T> > l, typename std::shared_ptr<Expression<T> > r) : l(l), r(r) {};
        virtual ~Multiplication() {};

        T evaluate() const
        {
                std::cout << "*";
                T ml = l->evaluate();
                T mr = r->evaluate();
                return ml * mr;
        };
};
Run Code Online (Sandbox Code Playgroud)

然后一位朋友问我为什么他的代码以"错误"的顺序产生输出.他有类似的东西

T evaluate() const
{
        std::cout << "*";
        return l->evaluate() * r->evaluate();
};
Run Code Online (Sandbox Code Playgroud)

r->evaluate()之前打印调试信息的代码l->evaluate().我也在我的机器上进行了测试,只需将这三条线改为单线.

所以,我想,那么*应该是从右到左的联想.但在互联网上,他们说这是从左到右.有一些额外的规则吗?使用模板时可能有些特别之处?或者这是VS2012中的错误?

Bar*_*rry 8

当我们说*从左到右的关联性时,我们的意思是表达式a*b*c*d将始终评估为(((a*b)*c)*d).而已.在您的示例中,您只有一个operator*,因此没有任何关联.

您遇到的是操作数的评估顺序.你在打电话:

operator*(l->evaluate(), r->evaluate());
Run Code Online (Sandbox Code Playgroud)

两个表达式都需要在调用之前进行评估operator*,但是C++标准未明确指定它们的评估顺序.在你的情况下,r->evaluate()首先得到评估 - 但这与关联性无关operator*.

请注意,即使您有a->evaluate() * b->evaluate() * c->evaluate(),也会将其解析为:

operator*(operator*(a->evaluate(), b->evaluate()), c->evaluate())
Run Code Online (Sandbox Code Playgroud)

基于运算符关联性的规则 - 但即使在这种情况下,也没有规则可以防止c->evaluate()首先被调用.它很可能是!