设为首页 加入收藏

TOP

4.1.3 求值顺序
2013-10-07 16:29:30 来源: 作者: 【 】 浏览:110
Tags:4.1.3 顺序

4.1.3  求值顺序

优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。在大多数情况下,不会明确指定求值的顺序。对于如下的表达式

  1. int i = f1() * f2(); 

我们知道f1和f2一定会在执行乘法之前被调用,因为毕竟相乘的是这两个函数的返回值。但是我们无法知道到底f1在f2之前调用还是f2在f1之前调用。

对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为(参见2.1.2节,第36页)。举个简单的例子,<<运算符没有明确规定何时以及如何对运算对象求值,因此下面的输出表达式是未定义的:

  1. int i = 0;  
  2. cout << i << " " << ++i << endl;    // 未定义的  

因为程序是未定义的,所以我们无法推断它的行为。编译器可能先求++i的值再求i的值,此时输出结果是1  1;也可能先求i的值再求++i的值,输出结果是0  1;甚至编译器还可能做完全不同的操作。因为此表达式的行为不可预知,因此不论编译器生成什么样的代码程序都是错误的。

有4种运算符明确规定了运算对象的求值顺序。第一种是3.2.3节(第94页)提到的逻辑与(&&)运算符,它规定先求左侧运算对象的值,只有当左侧运算对象的值为真时才继续求右侧运算对象的值。另外三种分别是逻辑或(||)运算符(参见4.3节,第141页)、条件( :)运算符(参见4.7节,第151页)和逗号(,)运算符(参见4.10节,第157页)。

求值顺序、优先级、结合律

运算对象的求值顺序与优先级和结合律无关,在一条形如f()+g()*h()+j()的表达式中:

优先级规定,g()的返回值和h()的返回值相乘。

结合律规定,f()的返回值先与g()和h()的乘积相加,所得结果再与j()的返回值相加。

对于这些函数的调用顺序没有明确规定。

如果f、g、h和j是无关函数,它们既不会改变同一对象的状态也不执行IO任务,那么函数的调用顺序不受限制。反之,如果其中某几个函数影响同一对象,则它是一条错误的表达式,将产生未定义的行为。

建议:处理复合表达式

以下两条经验准则对书写复合表达式有益:

1.拿不准的时候最好用括号来强制让表达式的组合关系符合程序逻辑的要求。

2.如果改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象。

第2条规则有一个重要例外,当改变运算对象的子表达式本身就是另外一个子表达式的运算对象时该规则无效。例如,在表达式*++iter中,递增运算符改变iter的值,iter(已经改变)的值又是解引用运算符的运算对象。此时(或类似的情况下),求值的顺序不会成为问题,因为递增运算(即改变运算对象的子表达式)必须先求值,然后才轮到解引用运算。显然,这是一种很常见的用法,不会造成什么问题。

4.1.3节练习

练习4.3:C++(www.cppentry.com)语言没有明确规定大多数二元运算符的求值顺序,给编译器优化留下了余地。这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,你认为这可以接受吗?请说出你的理由。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇1.2.2 如何使用函数模板 下一篇4.2 算术运算符

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: