#include <cstdio>
#include <iostream>
using namespace std;
unsigned n = 4242;
int getRemainderOf(int m, int n, int& quotient);
static int l = 0;
int main()
{
int quotient; // the value of which should be changed after calling the func.
for(int i=-1; i<=1; ++i)
{
for(int j=-1; j<=1; ++j)
{
if( i && j )
{
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) << " " << quotient <<endl;
cout << "("<< i*7 << "," << j*3 << ") " << getRemainderOf(i*7, 3*j, quotient) << " "; cout << quotient <<endl;
}
}
}
return 0;
}
int getRemainderOf(int m, int n, int& quotient)
{
++l;
cout << l <<endl;
quotient = m / n;
cout << " quotient " << quotient <<endl;
return m % n;
}
所以我期望在输出的第一行看到的是余数,然后是调用函数getRemainderOf()后得到的商。但相反,当我像这样看出商的价值时,我看到商的价值是垃圾值。所以即使我已经通过使用引用将它传递给函数,变量的值也不会改变。 有趣的是,如果我将其余部分(通过调用函数获得)和商分别进行cout,我会做对的。 我看到问题可能在于将函数作为运算符的参数调用&lt;&lt;函数,但我不知道为什么商的值没有改变,因为我在输出之前调用函数。这个运算符的关联性是从左到右所以这是错的? 那么请你告诉我这个输出的原因是什么。
答案 0 :(得分:0)
未指定函数参数的评估顺序。 在这些陈述中
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) << " " << quotient <<endl;
cout << "("<< i*7 << "," << j*3 << ") " << getRemainderOf(i*7, 3*j, quotient) << " "; cout << quotient <<endl;
有调用重载运算符&lt;&lt;实际上是功能。您必须将每个语句拆分为两个语句。例如
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) ;
cout << " " << quotient <<endl;
答案 1 :(得分:0)
您刚刚找到的是C ++怪癖之一的典型例子。您的程序实际上可以分解为这个简单的例子:
int i = 10;
f(i, ++i);
编译器可以从左到右选择函数参数求值,但这不能保证。这是一些标准文字:
5.2 / 4 Postfix Epressions [expr.post]
调用函数时,每个参数都应使用相应的参数进行初始化。 [注意:此类初始化相对于彼此不确定地排序(1.9) - 结束记录]
因为它们是不确定的顺序,编译器可以自由地在第一个参数之前评估++i
并使用相应的函数参数初始化它,然后评估i
并使用其相应的参数初始化它
函数调用参数评估歧义适用于此的原因是因为operator<<()
是一个函数,但它只是用运算符语法调用。例如,如果我们使用operator-id语法,那么这就是您的代码:
std::operator<<(std::operator<<(std::operator<<(std::cout, "(").operator<<(i*3), ",").operator<<(j*7), ")").operator<<(getRemainderOf(i*3, 7*j, quotient)).operator<<(quotient);
这些只是带参数的函数调用链,它们遵循与上面相同的规则。
解决方案是对修改对象并在operator<<()
调用中使用它的行为进行排序。您已经通过使用分号operator<<()
将;
调用分区为两个语句来实现此目的,因此保证在打印quotient
之前调用该函数。