Попробуйте изменить подпись ваших функций:
int ModifyRef( int& A );
void TakeValues( int X, int Y );
к следующему...
int& ModifyRef( int& A );
void TakeValues( int& X, int& Y );
и посмотрите, каким будет ваш вывод в main, когда вы вызовете эту строку кода:
int q = 9;
TakeValues( ModifyRef(q), q );
затем измените порядок параметров как таковой
TakeValues( q, ModifyRef(q) );
и сравните результаты.
Когда я сделал это на своей машине Win 7 64bit с сообществом VS2015 на Intel Core2 Quad Extreme, результаты, которые я получил для обеих ситуаций, когда использование ссылок было одинаковым, и результат, который я получаю, таков:
Я изменил значение A
в ModifyRef()
с 0 на 7 в целях тестирования.
int& A = 7
X = 7
Y = 7
для обеих ситуаций, когда либо внутренняя функция является первым параметром, а автономная переменная является вторым, либо внутренняя функция является вторым параметром, а автономная переменная является первой.
Поскольку я получаю те же результаты, мне кажется, что компилятор создает и обрабатывает указатель стека, ModifyRef()
, по-видимому, оценивается первым, и как только эта функция завершена, поскольку q
теперь ссылается вместо того, чтобы быть копией стека, это перезаписывается любым значением, которое оно было установлено в функции ModifyRef.
Я также немного модифицировал вашу функцию ModifyRef()
, чтобы я мог видеть, что ей передано в параметре, вместо того, чтобы иметь число, жестко закодированное в его операторе вывода.
int& ModifyRef( int& A ) {
A = 7; // Changed Value From 0 To 7 For Testing Purposes
std::cout << "n\int& A = " << A;
return A;
}
Однако этот эффект может применяться только при использовании только ссылок.
Когда я возвращаюсь к вашим исходным сигнатурам функций и вызываю их в следующем порядке:
q = 9;
TakeValues( ModifyRef( q ), q );
Поскольку ваш исходный код был представлен, я получаю вывод:
int& A = 7
X = 7
Y = 9
Однако, когда я изменяю параметры на:
q = 9;
TakeValues( q, ModifyRef( q ) );
Мой вывод:
int& A = 7
X = 7
Y = 7
Итак, то, что я вижу в этих двух ситуациях, немного отличается.
В первом порядке параметров Y
или второму параметру присваивается значение 9, поскольку q
инициализируется значением 9, а Y
внутри TakeValues()
печатает копию стека со значением 9. Затем X
оценивается ModifyRef()
, где q
имеет значение 9, но затем оно изменяется, поскольку оно является ссылкой, поэтому, когда TakeValues()
устанавливает X
из q
, q
уже было изменено с 9 на 7, поэтому X
теперь устанавливается на 7.
Во втором порядке параметров видно, что ModifyRef()
вызывается первым и изменяет q
с 9 на 7, поэтому TakeValues()
устанавливает Y
на 7, и, поскольку эта функция использует ссылку, q
также было изменено с 9 на 7, поэтому, когда первый параметр принимает q
для установки X
q
уже изменено с 9 на 7.
Я не знаю, зависит ли это от компилятора, но, по крайней мере, на моей машине кажется, что стек вызовов для параметров происходит от самого дальнего справа налево. Это также имеет смысл, когда вы думаете об этом из-за того, что функции имеют значения по умолчанию.
Пример:
class foo {
void bar( int a, int b, int c = 3 ) {
std::cout << a << ", " << b << ", " << c << std::endl;
}
};
Все значения по умолчанию в объявлении функции должны быть крайними справа, потому что у вас не может быть:
class foo {
void bar( int a = 1, int b, int c ) { ... } // Compile Error
};
Я надеюсь, что это поможет прояснить, что происходит в вашем коде, когда вы начинаете вызывать функцию внутри функции в качестве параметра, если вы используете передачу по значению (копия стека) или по ссылке.
person
Francis Cugler
schedule
02.02.2016
std::
как часть имен вещей из стандартной библиотеки,using namespace std;
не нужен. Кроме того, это серьезный нарушитель спокойствия. - person Pete Becker   schedule 02.02.2016