C ++输出具有嵌入式函数调用的求值顺序 [英] C++ Output evaluation order with embedded function calls

查看:118
本文介绍了C ++输出具有嵌入式函数调用的求值顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个介绍C ++类的TA。上周的测试中询问了以下问题:

I'm a TA for an intro C++ class. The following question was asked on a test last week:

以下程序的输出是什么:

What is the output from the following program:

int myFunc(int &x) {
   int temp = x * x * x;
   x += 1;
   return temp;
}

int main() {
   int x = 2;
   cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}

对我和所有同事来说,答案显然是:

The answer, to me and all my colleagues, is obviously:

8
27
64

但现在有几个学生指出,当他们在某些环境中运行时,他们实际上得到了相反的结果:

But now several students have pointed out that when they run this in certain environments they actually get the opposite:

64
27
8

在我的linux环境使用gcc我得到我会期望。在我的Windows机器上使用MinGW我得到他们在说什么。
它似乎是评估最后调用myFunc首先,然后第二个调用,然后第一,然后一旦它有所有的结果,它以正常的顺序,从第一个开始输出。但是因为调用次序是相反的。

When I run it in my linux environment using gcc I get what I would expect. Using MinGW on my Windows machine I get what they're talking about. It seems to be evaluating the last call to myFunc first, then the second call and then the first, then once it has all the results it outputs them in the normal order, starting with the first. But because the calls were made out of order the numbers are opposite.

在我看来,是一个编译器优化,选择以相反的顺序评估函数调用,但我真的不知道为什么。我的问题是:我的假设是否正确?这是在后台发生了什么?还是有什么完全不同的?此外,我真的不明白为什么会有一个好处,以评估功能向后,然后评估产出远期。输出必须向前,因为ostream的工作原理,但似乎功能的评估也应该向前。

It seems to me to be a compiler optimization, choosing to evaluate the function calls in the opposite order, but I don't really know why. My question is: are my assumptions correct? Is that what's going on in the background? Or is there something totally different? Also, I don't really understand why there would be a benefit to evaluating the functions backwards and then evaluating output forward. Output would have to be forward because of the way ostream works, but it seems like evaluation of the functions should be forward as well.

感谢您的帮助!

推荐答案

C ++标准没有定义完整表达式的子表达式的求值顺序,除了某些引入顺序的运算符运算符,三元运算符,短路逻辑运算符),以及构成函数/运算符的参数/操作数的表达式都在函数/运算符本身之前进行计算。

The C++ standard does not define what order the subexpressions of a full expression are evaluated, except for certain operators which introduce an order (the comma operator, ternary operator, short-circuiting logical operators), and the fact that the expressions which make up the arguments/operands of a function/operator are all evaluated before the function/operator itself.

GCC没有义务向你(或我)解释为什么它想要订购它们。它可能是一个性能优化,它可能是因为编译器代码出来了几行更短和更简单的方式,这可能是因为一个mingw编码器个人恨你,并希望确保,如果你做假设, t由标准保证,你的代码出错。欢迎来到开放标准的世界: - )

GCC is not obliged to explain to you (or me) why it wants to order them as it does. It might be a performance optimisation, it might be because the compiler code came out a few lines shorter and simpler that way, it might be because one of the mingw coders personally hates you, and wants to ensure that if you make assumptions that aren't guaranteed by the standard, your code goes wrong. Welcome to the world of open standards :-)

编辑添加:litb下面谈谈(未)定义的行为。该标准表示,如果在表达式中多次修改变量,并且对该表达式存在有效的求值顺序,使得该变量被修改多次,而中间没有序列点,则表达式具有未定义的行为。这在这里不适用,因为变量在函数调用中被修改,并且在任何函数调用的开始处有一个序列点(即使编译器嵌入它)。但是,如果您手动嵌入代码:

Edit to add: litb makes a point below about (un)defined behavior. The standard says that if you modify a variable multiple times in an expression, and if there exists a valid order of evaluation for that expression, such that the variable is modified multiple times without a sequence point in between, then the expression has undefined behavior. That doesn't apply here, because the variable is modified in the call to the function, and there's a sequence point at the start of any function call (even if the compiler inlines it). However, if you'd manually inlined the code:

std::cout << pow(x++,3) << endl << pow(x++,3) << endl << pow(x++,3) << endl;

那就是未定义的行为。在这段代码中,它是有效的编译器评估所有三个x ++子表达式,然后三个调用pow,然后开始对运算符< 。因为这个顺序是有效的并且没有分隔x的修改的序列点,所以结果是完全未定义的。在您的代码段中,只有执行顺序未指定。

Then that would be undefined behavior. In this code, it is valid for the compiler to evaluate all three "x++" subexpressions, then the three calls to pow, then start on the various calls to operator<<. Because this order is valid and has no sequence points separating the modification of x, the results are completely undefined. In your code snippet, only the order of execution is unspecified.

这篇关于C ++输出具有嵌入式函数调用的求值顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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