使用 std::cout 计算参数的顺序

发布于 2024-12-08 20:56:49 字数 639 浏览 1 评论 0原文

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

代码:

#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。感谢任何帮助!

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :

Code :

#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;
}

The output is :

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

Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你怎么敢 2024-12-15 20:56:49

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

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

The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).

If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.

樱娆 2024-12-15 20:56:49

这个问题的答案在 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,“不要这样做”的建议仍然是合理的。

The answer to this question changed in C++17.

Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).

Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.

(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).

So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.

茶花眉 2024-12-15 20:56:49

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

不要这样做。

Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.

Don't do this.

栀子花开つ 2024-12-15 20:56:49

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

这与带有运算符+示例的示例的情况相同:

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

The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point

This is the same situation as the example with the operator+ example:

Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.

怼怹恏 2024-12-15 20:56:49

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 

the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
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';
}

Notes

Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.


and in the section related to sequencing rules you can read the following:

Undefined behavior:

1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

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) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

cout << i << i++; // undefined behavior until C++17
a[i] = i++;       // undefined behavior until C++17
n = ++i + i;      // undefined behavior 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文