以下程序的输出是什么?
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; }
对我和所有同事的回答显然是:
8 27 64
但现在有几个学生已经指出,当他们在某些环境下运行时,他们实际上是相反的:
64 27 8
当我使用gcc在我的linux环境中运行它,我会得到我的期望.在我的Windows机器上使用MinGW,我得到他们在说什么.
它似乎在评估最后一次调用myFunc,然后是第二次调用,然后是第一次,然后一旦它有所有的结果,它以正常的顺序输出它们,从第一个开始.但是因为电话是按顺序排列的,所以数字是相反的.
在我看来,作为一个编译器优化,选择以相反的顺序来评估函数调用,但是我不知道为什么.我的问题是:我的假设是否正确?这是背景中发生了什么吗?还是有完全不同的东西?此外,我不明白为什么会有一个好处来评估功能,然后评估输出向前.由于ostream的工作方式,产出必须向前推进,但似乎对功能的评估也应该是前进的.
谢谢你的帮助!
解决方法
海湾合作委员会没有义务向你(或我)解释为什么要按照这样的方式订购.这可能是一个性能优化,这可能是因为编译器代码出现了更短和更简单的几行,这可能是因为其中一个mingw编程人员亲自憎恨你,并希望确保如果你做出假设,标准保证,您的代码出错.欢迎来到开放标准的世界:-)
编辑添加:litb在下面描述(un)定义的行为.该标准表示,如果您在表达式中多次修改变量,并且如果存在该表达式的有效的评估顺序,以使变量多次修改,而其间没有序列点,则该表达式具有未定义的行为.这在这里不适用,因为变量在调用函数时被修改,并且在任何函数调用的开始都有一个序列点(即使编译器内联它).但是,如果您手动内嵌代码:
std::cout << pow(x++,3) << endl << pow(x++,3) << endl;
那么这将是未定义的行为.在这段代码中,编译器对所有三个“x”子表达式进行求值,然后对pow进行三次调用,然后开始对运算符<<<因为这个顺序是有效的,没有分离x的修改的顺序点,结果是完全未定义的.在你的代码片段中,只有执行顺序是未指定的.