奇怪的输出,不像预期的那样

时间:2014-07-19 11:44:34

标签: c++ reference stream iostream cout

很抱歉问你一个愚蠢的问题,但我无法弄清楚为什么我继续得到这个输出。 所以这是我的代码:

#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;函数,但我不知道为什么商的值没有改变,因为我在输出之前调用函数。这个运算符的关联性是从左到右所以这是错的? 那么请你告诉我这个输出的原因是什么。

2 个答案:

答案 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之前调用该函数。