前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++求值顺序

C++求值顺序

作者头像
Enterprise_
发布2019-02-21 17:17:30
1.3K0
发布2019-02-21 17:17:30
举报
文章被收录于专栏:小L的魔法馆小L的魔法馆
代码语言:javascript
复制
《C++Primer5th》中文版第124页
C++语言没有明确规定大多数二元运算符的求值顺序,
给编译器优化留下了余地。
这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,这个是否可以接受?

1.首先可以知道优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。

比如:

代码语言:javascript
复制
int i=f1()*f2();

在这里虽然f1和f2在乘法之前被调用,但是f1先调用还是f2先调用却不得而知。

2.再比如结合律:

代码语言:javascript
复制
int i=0;
cout<<i<<" "<<+i<<endl;

结果可能是0 1或者是1 1. 因为虽然<<是左结合,但是对于那些没有明确规定运算对象的求值顺序的运算符而言,求值顺序就和优先级,以及结合律无关。 所以上面的式子是未定义的,即如果表达式指向并且修改了同一个对象,这样的行为就是未定义的

  • 逻辑与&&
  • 逻辑非||
  • 条件?: -逗号, 上面四种运算符明确规定了运算对象的求值顺序。

3.C++手册

几乎所有 C++ 运算符的求值顺序(包括函数调用表达式中的函数参数求值顺序和任何表达式中子表达式的求值顺序)都是未指定的。编译器能以任何顺序求值,并可以在再次求值相同表达式时选择另一顺序。 例子: 表达式 f1() + f2() + f3() 由于 operator+ 的从左到右结合性分析为 (f1() + f2()) + f3() ,但运行时对 f3 的函数调用可能首先、最后,或在 f1() 和 f2() 之间求值。

4.序列点规则(以下内容来自C++手册

序列点规则 (C++11 前) 定义 求值可能产生副效应:即访问 volatile 左值所指代的对象、修改对象、调用库 I/O 函数或调用做任何这些动作的函数。

序列点( sequence point )是执行序列中的点,在该点所有来自序列中先前求值的副效应均已完成,而后继求值的副效应都未开始。

规则 1) 每个完整表达式结尾(典型地在分号)有一个序列点。

2) 调用函数时(无论该函数是否内联,无论是否使用函数调用语法),所有函数参数的求值(若存在)后有一个序列点,它在函数体内的任何表达式或语句执行前发生。

3) 复制函数返回值后,和函数外任何语句的执行前有一个序列点。

4) 一旦函数执行开始,则在被调用函数完成前,不求值来自调用方函数的表达式(函数不能交错)。

5) 每个使用内建(非重载)运算符的下列四种表达式的求值中,表达式 a 的求值后有一个序列点。

代码语言:javascript
复制
a && b
a || b
a ? b : c
a , b

未定义行为 - 1) 前后序列点间,至多可以修改标量对象的存储值一次,否则行为未定义。

代码语言:javascript
复制
i = ++i + i++; // 未定义行为
i = i++ + 1; // 未定义行为( C++17 前)
i = ++i + 1; // 未定义行为( C++11 前)
++ ++i; // 未定义行为( C++11 前)
f(++i, ++i); // 未定义行为( C++17 前)
f(i = -1, i = -1); // 未定义行为( C++17 前)
  • 2) 前后序列点间,访问表达式求值所修改的标量对象的先前值,必须只为确定要存储的值。若以任何其他方式访问,则行为未定义。
代码语言:javascript
复制
cout << i << i++; // 未定义行为( C++17 前)
a[i] = i++; // 未定义行为( C++17 前)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年03月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.首先可以知道优先级规定了运算对象的组合方式,但是没有说明运算对象按照什么顺序求值。
  • 2.再比如结合律:
  • 3.C++手册
  • 4.序列点规则(以下内容来自C++手册)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档