6

这是我今天编码的

#include <iostream>
using namespace std;

int function1()
{
  cout<<"hello from function1()"; return 0;
}

int function2()
{
  cout<<"hello from function2()"; return 0;
}

int main()
{
    int func_diffresult = 0;
    func_diffresult = function1() - function2();
    cout<<func_diffresult; /** prints 0 correctly **/
}

输出是 get is hello from function2()hello from function1()。我认为输出应该是hello from function1()hello from function2(). 我的编译器在玩我吗?

4

3 回答 3

11

-运算符参数的求值顺序未指定。所以函数可以按任意顺序调用。

于 2010-09-23T01:25:10.707 回答
6

-运算符有效地变为operator-(function1(), function2()),并且故意未指定函数参数的评估顺序。


相关说明:

不指定它的一个非常好的理由是有效地处理调用约定。例如,C 调用约定要求参数以相反的顺序压入堆栈。

因此,以相反的顺序评估函数是有意义的,因为结果可能会立即推送。从左到右评估参数然后从右到左推送结果涉及在推送任何结果之前存储所有结果。如果你真的需要这样做,你可以手动进行。如果这对您无关紧要,那么性能优势可能确实如此。

于 2010-09-23T01:28:27.830 回答
2

ISO 标准不保证评估子表达式的顺序。

来自 c++0x 标准草案:


1.9。Program execution:
      :
13/ Sequenced before 是由单个线程执行的评估之间的不对称、传递、成对关系,这会在这些评估中产生偏序。给定任意两个评估 A 和 B,如果 A 在 B 之前排序,则 A 的执行将在 B 的执行之前。如果 A 没有在 B 之前排序并且 B 没有在 A 之前排序,那么 A 和 B 是无序的。[注意:未排序的评估的执行可以重叠。]

当 A 在 B 之前排序或 B 在 A 之前排序时,评估 A 和 B 的排序不确定,但未指定哪个。[注意:不确定顺序的评估不能重叠,但可以先执行。]
     
15/除非另有说明,否则单个运算符的操作数和单个表达式的子表达式的求值是无序的。
     
当调用一个函数时(无论该函数是否内联),与任何参数表达式或与指定被调用函数的后缀表达式相关的每个值计算和副作用都在执行主体中的每个表达式或语句之前进行排序被调用的函数[脚注:换句话说,函数执行不会相互交错]。[注意:与不同参数表达式相关的值计算和副作用是无序的。]

调用函数(包括其他函数调用)中的每个求值,如果在被调用函数的主体执行之前或之后没有特别排序,则相对于被调用函数的执行是不确定的。


换句话说,实现可以使用它想要的任何方法自由地安排调用。但是,函数调用根据脚注进行特殊处理 - 它们不会交错。

于 2010-09-23T02:28:15.340 回答