定义的参数评估顺序导致次优代码? [英] Defined argument evaluation order leads to sub-optimal code?

查看:88
本文介绍了定义的参数评估顺序导致次优代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个已知的事实是c和c ++中的参数求值顺序没有定义:
例如: foo(a(),b())在上面的调用中,由编译器的实现来决定哪个顺序的求值选择并且因此首先执行哪个函数。最近我的一个朋友问为什么在C或C ++中未指定评估顺序。当我搜索它,我知道指定一个评估顺序会导致次优代码生成。但是怎么会这样呢?为什么定义的参数求值顺序会导致次优代码?当我提到Java的参数评价顺序。我在规范中找到了以下内容。


15.7.4。参数列表从左到右进行评估



在方法或构造函数调用或类实例创建表达式中,
参数表达式可能出现在括号内,逗号。每个参数
表达式在任何参数表达式的任何部分之前都显示为完全求值,其值为

如果参数表达式的评估突然完成,其右侧的任何参数
表达式的任何部分都没有被评估过?


在这种情况下,Java有一个定义的参数求值顺序,但是说C或C ++编译器会产生次优的代码,如果这样的行为被指定似乎有点奇怪。

解决方案

这是部分历史的:在具有少数寄存器的处理器上,对于
示例,一个传统的(和简单的)优化技术是
评估需要最多的寄存器的子表达式。如果一个
子表达式需要5个寄存器,而另一个4,例如,
可以保存需要5的寄存器的结果,而不需要
。 p>

这可能与通常认为的不太相关。如果表达式没有副作用,或
重新排序不改变程序的可观察行为,编译器可以重新排序(甚至在Java中)

现代编译器能够在二十多年前(当制定C ++规则时)比编译器
更好地确定它。和
可能是,当他们不能确定这一点,你在每个表达式中做足够的
,额外的溢出到内存不重要。



至少,这是我的直觉。我已经被至少一个人
告知,他实际上在优化器上工作,这将导致重大的
差异,所以我不会说我相信这一点。



编辑:



只是添加一些关于Java模型的注释。当Java是
设计时,它被设计为一个解释朗读。极端的
性能不是一个问题;目标是极端安全,和
可再现性。因此,它非常精确地指定了许多事情,所以
任何编译的程序将有完全相同的行为
无论平台。应该没有未定义的
行为,没有实现定义的行为,没有未指定的
行为。不管成本(但相信这可能是
在任何最广泛的机器上以合理的成本完成)。一个
C(和间接C ++)的初始设计目标是不必要的
额外的运行时成本应该是最小的,平台之间的一致性
不是一个目标(因为在时间,甚至常见平台变化很大
),而安全,虽然一个关注,不是原始的。虽然
的态度已经演变了一些,仍然有一个目标是能够
支持,有效地,任何机器可能在那里。没有
需要最新,最复杂的编译器技术。不同的
目标自然会导致不同的解决方案。


It is a known fact that argument evaluation order in c and c++ are not defined: for example: foo(a(),b()) In the above call it is up to the implementation of the compiler to decide which order of evaluation to pick and hence forth which function to execute first. Lately one of my friends asked why is the order of evaluation unspecified in C or C++. When I googled it, I came to know that specifying an evaluation order would lead to sub-optimal code generation. But how is it so? Why would a defined order of evaluation of arguments lead to sub-optimal code? And when I referred to Java's argument evaluation order. I found the following in the spec.

15.7.4. Argument Lists are Evaluated Left-to-Right

In a method or constructor invocation or class instance creation expression, argument expressions may appear within the parentheses, separated by commas. Each argument expression appears to be fully evaluated before any part of any argument expression to its right. If evaluation of an argument expression completes abruptly, no part of any argument expression to its right appears to have been evaluated?

That being the case, Java has a defined argument evaluation order, but saying C or C++ compilers would yield sub-optimal code if such a behavior is specified seems a little odd. Can you throw some light on this?

解决方案

It's partially historical: on processors with few registers, for example, one traditional (and simple) optimization technique is to evaluate the subexpression which needs the most registers first. If one subexpression requires 5 registers, and the other 4, for example, you can save the results of the one requiring 5 in the register not needed by the one requiring 4.

This is probably less relevant that usually thought. The compiler can reorder (even in Java) if the expressions have no side effects, or the reordering doesn't change the observable behavior of the program. Modern compilers are able to determing this far better than compilers twenty or more years ago (when the C++ rule was formulated). And presumably, when they aren't able to determine this, you're doing enough in each expression that the extra spill to memory doesn't matter.

At least, that's my gut feeling. I've been told by at least one person who actually works on optimizers that it would make a significant difference, so I won't say that I'm sure about it.

EDIT:

Just to add some comments with regards to the Java model. When Java was being designed, it was designed as an interpreted langauge. Extreme performance wasn't an issue; the goal was extreme safety, and reproduceability. Thus, it specifies many things very precisely, so that any program which compiles will have exactly the same behavior regardless of the platform. There was supposed to be no undefined behavior, no implementation defined behavior, and no unspecified behavior. Regardless of cost (but with the belief that this could be done at reasonable cost on any of the most widespread machines). One initial design goals of C (and indirectly C++) was that unnecessary extra runtime cost should be minimum, that consistency between platforms wasn't a goal (since at the times, even common platforms varied greatly), and that safety, while a concern, wasn't primordial. While the attitudes have evolved some, there is still a goal to be able to support, efficiently, any machine which might be out there. Without requiring the newest, most complex compiler technologies. And different goals naturally lead to different solutions.

这篇关于定义的参数评估顺序导致次优代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆