通过引用和返回的C++函数调用不是预期的.

Evy*_*ino 0 c++

我写了一个简单的函数如下......

int fun(int *i, int *j) 
{  
     *i += 3; 
     *j += *i; 
     return (*i + *i); 
}
Run Code Online (Sandbox Code Playgroud)

在主函数中,我将函数调用如下...

int main()
{
    int x = 3, y = 2, a, b; 
    a = x + y + fun(&x, &y) + x; 
    b = y + fun(&x, &y) + y;

    cout<<" a = " << a << "\n";
    cout<<" b = " << b << "\n";

}
Run Code Online (Sandbox Code Playgroud)

现在问题是输出不如预期

运行后这是输出

a=23
b=52
Run Code Online (Sandbox Code Playgroud)

我在期待

a=23 
b=46
Run Code Online (Sandbox Code Playgroud)

我不知道究竟是否有人可以解释.

And*_*owl 5

评估表达式的结果未指定,因为评估xfun(&x, &y)不确定地排序.

请注意,一个表达式评估,才可产生未指定的结果并不能意味着你的程序未定义的行为; 相反,它意味着你不能分辨出那个表达式的评估会产生哪些有限的可能结果.

在这里解释标准可能相当棘手(实际上,在原始答案中我用错误的方式解释它 - 感谢Jerry Coffin注意到).

要了解为什么这可能很棘手,让我们考虑C++ 11标准第1.9/15段的第一部分:

除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的评估是不确定的.[...]在运算符结果的值计算之前,对运算符的操作数的值计算进行排序.如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,则行为未定义.

例如,给定一个表达式,其中包括计算两个子表达式的总和,例如(考虑operator +这里不重载):

e1 + e2
Run Code Online (Sandbox Code Playgroud)

如果评估e1使用某个标量的值s,并且评估e2对该值有副作用,则行为是不确定的.例如,评估:

(i + i++)
Run Code Online (Sandbox Code Playgroud)

由于上面引用的句子,给出了未定义的行为.

但是,你的情况有所不同.后面的同一段落规定:

当调用函数时(无论函数是否为内联函数),[...]调用函数中的每个求值(包括其他函数调用)在执行被调用函数体之前或之后都没有特别排序.关于被调用函数的执行,不确定地排序.

这意味着如果要评估的表达式如下所示:

i + f(i)
Run Code Online (Sandbox Code Playgroud)

并且f(i)增量i,行为不再是未定义的,但只是未指定.换句话说,你的编译器允许评估if(i)以任何顺序,但可能的结果是这些可能的评估之一而造成的.

另一方面,如果行为未定义,则可能的结果可能是任何事情(从崩溃到行为与预期一致,在控制台上打印奇怪的消息等等).