使用std :: cout评估参数的顺序

时间:2011-10-10 20:49:22

标签: c++ visual-studio stdout language-lawyer

大家好我今天偶然发现了这段代码,我对于究竟发生了什么以及更具体的顺序感到困惑:

代码:

#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和MSVS 2010.感谢任何帮助!

5 个答案:

答案 0 :(得分:22)

表达式中元素的评估顺序未指定(除了一些非常特殊的情况,例如&&||运算符以及引入序列点);所以,不能保证testfoo(test)之前或之后进行评估(修改它)。

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

答案 1 :(得分:10)

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

不要这样做。

答案 2 :(得分:5)

这个问题的答案在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 :(得分:2)

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

这与使用operator + example的示例相同:

  

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

答案 4 :(得分:0)

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