2015-06-07 43 views
2

在学校任务上工作时,我们必须对运算符重载和模板进行操作。很酷。我写道:C++:*(multiply)运算符的关联性不是从左到右

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; 
     }; 
}; 

然后一个朋友问我为什么他的代码以“错误”的顺序产生输出。 他有这样的事情

T evaluate() const 
{ 
     std::cout << "*"; 
     return l->evaluate() * r->evaluate(); 
}; 

l->evaluate()之前的r->evaluate()打印的调试信息的代码。 我在我的机器上测试了它,只需将这三行改为一行即可。

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

+7

联合性与评估顺序不一样。 –

+0

似乎是这样的关键:)我会做一些研究,谢谢。 –

+0

[运算符优先级与评估顺序](http:// stackoverflow。com/questions/5473107/operator-precedence-vs-order-of-evaluation) –

回答

8

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

你正在运行的是操作数的评估顺序。您在呼唤:

operator*(l->evaluate(), r->evaluate()); 

两个表达式需要调用之前进行评估,以operator*,但它是不确定的(明确)由C++标准什么样的顺序,他们在你的情况,r->evaluate()得到了第一次评估得到评估 - 。但这与operator*的结合性无关。基于运营商关联规则

operator*(operator*(a->evaluate(), b->evaluate()), c->evaluate()) 

- 但即使在这种情况下,没有规则,以防止c->evaluate()从第一次被称为:

注意,即使你有a->evaluate() * b->evaluate() * c->evaluate()的是,因为这将得到解析。它可能很好!

+0

谢谢!说得通! :) –

2

您的表达单一运营商:

l->evaluate() * r->evaluate() 

所以关联性不参与的都在这里。值得注意的是在调用*运算符之前评估两个操作数,并且未定义它们的评估顺序。允许编译器以任何合适的方式重新排序评估。

在C++ 11中,对operator*的调用在操作数评估之后被排序,但两个评估之间没有顺序关系。从n4296 draft (post C++14),第10页:

§1.9.15除非另有说明,个体经营者和个人表达的子表达式的操作数的评价是未测序。

相关问题