这段代码是否定义明确?
此代码取自此处的讨论。
someInstance.Fun(++k).Gun(10).Sun(k).Tun();
这段代码是否定义明确? Fun()中的++k
是否在Sun()中的k
之前进行了评估?
如果k
是用户定义的类型,而不是内置类型怎么办?以上函数调用顺序的方式与此不同:
eat(++k);drink(10);sleep(k);
据我所知,在这两种情况下,每个函数调用后都存在一个序列点。如果是这样,为什么第一个案例也不能像第二个案例那样明确定义?
C ++ ISO标准的1.9.17部分对序列点和功能评估进行了说明:
调用函数时(无论是否为
不是函数是内联的),有
评估后的序列点
所有函数参数(如果有)
这是在执行之前发生的
中的任何表达或陈述
功能体。还有一个
复制后的序列点
返回值和之前
在外面执行任何表达式
功能。
没有找到相关结果
已邀请:
6 个回复
羔磺
。以下是明确定义的
如果将参数类型
更改为
,则它将变为未定义。让我们画出一张
版本的树。
可以看出,我们读取了
(由
表示)和
(在最顶部)的副作用,它们没有被序列点分开:在这个表达式中,相对于彼此的子表达式,根本没有序列点。最底部
表示全表达序列点。
粱委教
这给我们的唯一保证是:
在拨打
之前进行评估,并且
在拨打
之前进行评估。 但是这样的订单仍然是可能的: 评估
评估
(序列点从
调用分离
) 叫
(序列点从
调用分离
) 叫
当然,我们也可以调换前两项,在
之前评估
。为什么不?该标准仅要求在函数体的第一个语句之前完全评估函数的参数,并且上述序列满足该要求。 这是我的解释,至少。它似乎没有说在参数评估和函数体之间不会发生任何其他事情 - 只是那两个被序列点分开。
慰泥悍瓶
是不同的,因为
是一个序列点,因此评估的顺序是明确定义的。
断跑胺弄萎
我使用gcc 3.4.6运行它并且没有优化并得到:
......用-O3 ......
因此,无论是3.4.6的版本都有一个主要的错误(这有点难以置信),或者正如Philip Potter建议的那样,序列未定义。 (GCC 4.1.1有/无-O3产生5,5,5,5。) 编辑 - 我在以下评论中的讨论摘要: 3.4.6确实可能有一个bug(嗯,是的) 许多较新的编译器碰巧产生5/5/5/5 ......这是一个定义的行为吗? 可能不是,因为它对应于在进行任何函数调用之前被“操作”的所有增量副作用,这不是标准所保证的任何人都建议的行为。 这不是一个非常好的方法来调查标准的要求(特别是对于像3.4.6这样的旧编译器):同意,但它是一个有用的健全性检查
亲奋漏
并使用标准优化(在C ++模式下)编译,它给出: /tmp/webcompile/_13371_0.cc:在函数'int main(int,char **)'中: /tmp/webcompile/_13371_0.cc:16:警告:'i'上的操作可能未定义 我觉得有趣(其他任何编译器都警告过这个吗?Comeau在线没有) 另外,它还产生了以下中间表示(向右滚动):
显然,Clang的行为类似于gcc 4.x.x,并且在执行任何函数调用之前首先计算所有参数。
垫歌蝎降凤