извините за то, что задал вам глупый вопрос, но я просто не могу понять, почему я продолжаю получать этот результат. Итак, вот мой код:
#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(). Но вместо этого, когда я отказываюсь от значения частного, я вижу, что значение частного является значением мусора. Поэтому значение переменной не изменяется, хотя я передал ее функции, используя ссылку. Самое забавное, что если я оставлю остаток (получив вызов функции) и частное, я получу его правильно. Я вижу, что проблема может заключаться в вызове функции в качестве аргумента функции operator <<, но я не понимаю, почему значение quotient не изменяется, так как я вызываю функцию до ее вывода. Эта ассоциативность операторов слева направо, так что неправильно? Не могли бы вы рассказать мне, в чем причина этого выхода.
То, что вы только что нашли, является классическим примером одного из причуд C++. Ваша программа может быть разложена на этот простой пример:
int i = 10;
f(i, ++i);
У компилятора есть выбор оценки аргументов функции слева направо, но это не гарантируется. Вот некоторый стандартный текст:
5.2/4 Postfix Epressions [expr.post]
Когда вызывается функция, каждый параметр должен быть инициализирован соответствующим аргументом. [Примечание: такие инициализации индетерминированно упорядочены относительно друг друга (1.9) - примечание конца)
Поскольку они неопределенно упорядочены, компилятор имеет право оценивать ++i
до первого аргумента и инициализировать его соответствующим параметром функции, а затем оценивать i
и инициализировать его соответствующим параметром next.
Признак неопределенности аргумента функции аргумента функции применим здесь, потому что 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
.
Порядок оценки аргументов функции не указан. В этих заявлениях
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;
называются перегруженные операторы <<, которые на самом деле являются функциями. Вы должны разделить каждое утверждение в двух утверждениях. Например
cout << "("<< i*3 << "," << j*7 << ") " <<( getRemainderOf(i*3, 7*j, quotient) ) ;
cout << " " << quotient <<endl;