调用函数的顺序错误。

4

这是我今天编写的代码

#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 **/
}

输出结果是hello from function2()hello from function1(),我认为输出应该是hello from function1()hello from function2()。我的编译器在和我开玩笑吗?

你的代码里可能有一个打字错误...我看到了两个 function1 声明。 - dmckee --- ex-moderator kitten
1
这段代码无法编译,因为你缺少第二个函数!请将第二个函数重命名为function2()。 - Secko
@dmckee修正了打字错误。 - Raghvan
3个回答

11
< p > < code > - 操作符的参数求值顺序是未指定的。因此,函数可以按任意顺序调用。


6
- 运算符实际上变成了 operator-(function1(), function2()),而函数参数的计算顺序是有意未指定的。

相关注释:

不指定函数参数计算顺序的一个非常好的理由是有效地处理调用约定。例如,C 调用约定要求参数以相反的顺序被推送到堆栈中。

因此,按相反顺序计算函数是有道理的,因为结果可能会立即被推送。从左到右计算参数,然后从右到左推送结果涉及存储所有结果,然后再推送它们。如果您真的需要这样做,可以手动完成。如果对您来说不重要,则性能收益可能很大。


这对于 x86 上的 cdecl 是正确的,但并不是所有的调用约定都将值推送到堆栈上。其中一些在寄存器中传递参数。 - dan04
当然。这就是为什么顺序是“未指定”的,而不是“从右到左”(或“从左到右”)-谁知道将来会使用什么调用约定?最好说“不要依赖参数顺序匹配评估顺序”,让编译器尽可能高效地完成它们的工作。 - Zooba

2
ISO标准不保证子表达式的计算顺序。根据C++0x草案标准,程序执行中的每个单线程评估都有一个部分顺序,这是一种非对称,传递性的成对关系。给定任意两个评估A和B,如果A在B之前排序,则A的执行应在B之前。如果A没有在B之前排序,且B也没有在A之前排序,则A和B未排序。注意:未排序评估的执行可以重叠。当A在B之前排序或B在A之前排序时,评估A和B是不确定排序的,但未指定哪个先执行。注意:不确定排序的评估不能重叠,但是可能先执行其中任何一个。除非另有说明,否则单个表达式的子表达式和各个运算符的操作数的评估未排序。调用函数时(无论函数是否为内联),与任何参数表达式或指定所调用函数的后缀表达式相关联的每个值计算和副作用都在调用函数主体中的每个表达式或语句执行之前排序。注:与不同参数表达式相关联的值计算和副作用未排序。在调用函数的主体执行之前,调用函数中的每个评估(包括其他函数调用)如果没有特别排序,则与调用函数的执行是不确定排序的。换句话说,实现可以使用任何方法来安排调用。但是,根据脚注,函数调用被特别处理-它们不会交错执行。

只是好奇:这是否意味着在多CPU架构上,function1和function2也可以交错执行(从而并行运行)? - Chubsdad
我想是这样的。因为无论是A在B之前还是B在A之前,但未指定顺序的标准术语是“不确定排序”。但由于标准说“未排序”,在我看来,这意味着函数调用也可以交错。 - Chubsdad
@Chubsdad:是的,请看更新(第13段的最后一句话和第一段末尾的注释,以及整个第二段)。对于未排序的操作,它们可以重叠。对于不确定排序的操作,它们仍然是有序的(没有重叠),但可能是AB或BA。这个问题涉及到一个未排序的操作,所以它 可能 会重叠。 - paxdiablo
函数调用永远不能交错执行:"8 / 一旦函数开始执行,直到被调用的函数执行完成,来自调用函数的任何表达式都不会被评估。(脚注:换句话说,函数执行不会相互“交错”)。"显然,在某些情况下可以应用 as-if 规则。 - dave
很好的发现,@dave,我没有看到那个。已更新以修复。 - paxdiablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接