使用 std::cout 计算参数的顺序
大家好,我今天偶然发现了这段代码,我对到底发生了什么以及更具体的顺序感到困惑:
代码:
#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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
表达式中元素的计算顺序是未指定的(除了一些非常特殊的情况,例如
&&
和||
运算符以及三元运算符,它们引入 < 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 thattest
will be evaluated before or afterfoo(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.
这个问题的答案在 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.评估顺序未指定。它不是从左到右、从右到左或其他任何顺序。
不要这样做。
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
评估顺序未指定,请参阅 http://en.wikipedia.org/wiki/Sequence_point
这与带有运算符+示例的示例的情况相同:
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:
C++ 参考很好地解释了为什么永远不应该这样做(导致 UB 或未定义的行为)
https://en.cppreference.com/w/cpp/language/operator_incdec
在与排序规则相关的部分中,您可以阅读以下内容:
未定义行为:
1) 如果标量对象上的副作用相对于标量对象上的另一个副作用未排序相同的标量对象,行为未定义。
2) 如果标量对象上的副作用相对于使用同一标量对象的值的值计算是无序的,则该行为是未定义的。
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
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.
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.