大家好,我今天偶然发现了这段代码,我对到底发生了什么,更具体地是按照什么顺序感到困惑:

代码:

#include <iostream>

bool foo(double & m)
{
    m = 1.0;
    return true;
}

int main()
{
    double test = 0.0;
    std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) <<  "\tValue of test : " << test << std::endl;
    return 0;
}


输出为:

Value of test is :      1       Return value of function is : 1 Value of test : 0


看到这一点,我认为在调用函数之前会以某种方式打印最右边的参数。所以这是从右到左的评估?尽管在调试过程中,该函数似乎在输出之前被调用,这是我所期望的。我正在使用Win7和MSVS2010。不胜感激!

#1 楼

未指定表达式中元素的评估顺序(某些特殊情况除外,例如&&||运算符以及引入序列点的三元运算符);因此,不能保证在test(对其进行修改)之前或之后都会对foo(test)进行评估。

如果您的代码依赖于特定的求值顺序,则获取代码的最简单方法是将表达式拆分为多个单独的语句。

评论


您知道使用||的技巧吗?或&&强制执行<<链中的某个评估顺序?

– alfC
16年5月20日在23:12

不,但是我知道使用;并在换行符之后重复流变量;-)

–意大利Matteo
16年5月21日在3:25

也许使用C ++ 17标准中引入的更改来更新此答案将对以后在此绊脚的人们有所帮助:stackoverflow.com/a/50361417/9385966

– gflegar
18年5月16日在2:12



#2 楼

这个问题的答案在C ++ 17中已更改。

现在,重载运算符的评估与内置运算符的排序方式相同(C ++ 17 [over.match.oper] / 2)。

此外,现在<<>>和下标运算符的左操作数现在在右之前,并且函数调用的后缀表达式在对参数求值之前进行了排序。

(其他二进制运算符保留其先前的顺序,例如+仍未排序)。

因此问题中的代码现在必须输出Value of test is : 0 Return value of function is : 1 Value of test : 1。但是建议“不要这样做”仍然是合理的,因为每个人都需要一些时间才能更新到C ++ 17。

#3 楼

未指定评估顺序。它不是从左到右,从右到左或其他任何方法。

不要这样做。

#4 楼

未指定评估顺序,请参见http://en.wikipedia.org/wiki/Sequence_point

这与带有operator +示例的示例相同:


考虑两个函数f()g()。在C和C ++中,+运算符未与序列点关联,因此在表达式f()+g()中,有可能先执行f()g()


#5 楼

C ++参考很好地解释了为什么永远不应该这样做(导致UB或不确定的行为)
https://en.cppreference.com/w/cpp/language/operator_incdec

#include <iostream>

int main()
{
    int n1 = 1;
    int n2 = ++n1;
    int n3 = ++ ++n1;
    int n4 = n1++;
//  int n5 = n1++ ++;   // error
//  int n6 = n1 + ++n1; // undefined behavior
    std::cout << "n1 = " << n1 << '\n'
              << "n2 = " << n2 << '\n'
              << "n3 = " << n3 << '\n'
              << "n4 = " << n4 << '\n';
}



注意事项

由于涉及的副作用,必须小心使用内置的递增和递减运算符,以避免不确定的行为由于
违反了排序规则。



,在与排序规则有关的部分中,您可以阅读以下内容:

未定义行为:

1)如果相对于同一标量对象的另一个副作用,未对标量对象的副作用进行排序,则该行为未定义。

i = ++i + 2;       // undefined behavior until C++11
i = i++ + 2;       // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i);       // undefined behavior until C++17, unspecified after C++17
i = ++i + i++;     // undefined behavior


2)如果相对于使用同一标量对象的值进行的值计算,对标量对象的副作用未排序,则行为是不确定的。

cout << i << i++; // undefined behavior until C++17
a[i] = i++;       // undefined behavior until C++17
n = ++i + i;      // undefined behavior