У меня возникли проблемы с пониманием того, когда использовать & с переменной. Я думаю, что он меняет область действия на эту функцию, но по какой-то причине этот код не работает.
void advanceTimeInMinutes(int& hours, int& minutes, int& advances)
{
if(advances >=60-minutes){
hours++;
minutes=60-minutes+advances;
}else{
minutes +=advances;
}
}
и он называется
advanceTimeInMinutes( hour, minute, 50 );
Во многих языках программирования имя, которое вы используете для ссылки на объект, отличается от самого объекта. Один объект может иметь несколько имен.
Самый прямой способ присвоить несколько имен одному объекту в C++ - объявить имя с помощью &
specifier. (Это использование отличается от оператора &
, спецификатор не является оператором.)
Когда вы объявляете эти параметры с помощью &
, они становятся псевдонимами объекта, переданного в качестве аргумента функции. Такие имена называются ссылками.
C++ имеет несколько (хорошо, много) видов и категорий выражений. Двумя важными понятиями являются изменчивость и право собственности. Когда вы передаете ссылку на функцию, вы произвольно даете ей разрешение на изменение объекта и владение объектом. Модифицируемость указывается отсутствием спецификатора const
, а право собственности указывается с помощью &&
вместо &
(это новое в C++ 11).
Функция не может получить модифицируемый, не имеющий доступа доступ к объекту с только временным существованием, поскольку он должен иметь возможность ожидать, чтобы результаты были получены в такой объект для возврата к вызывающему. Значение 50
сохраняется в таком переходном объекте.
Одним из решений является использование int const & advances
, но лучшим решением является не использование ссылки вообще, потому что вы на самом деле не пытаетесь использовать имя псевдонимов для ссылки на общий объект.
Многие из них делают концептуальное предположение о том, что ссылка является автоматически-разыменованным указателем const
. Это работает очень хорошо, и компиляторы почти всегда так поступают. Но это не обязательно так. Например, учитывая это определение класса:
struct s {
static int x;
int &r = x;
char c;
};
Компилятор мог определить, что r
всегда ссылается на глобальный x
и заменяет каждое использование r
на x
. Если нет необходимости хранить ссылку в каждом объекте, sizeof(s)
может легально быть 1.
Это более продвинутый, чем текущий анализ кода C++, но это неизбежно произойдет в какой-то момент. Будущий код не должен ожидать, что реализация ссылок будет эквивалентна указателям.
&
является ссылочным оператором. Он использовался для изменения значения внутри функции. Приведенный выше код эквивалентен
void advanceTimeInMinutes(int *hours, int *minutes, int *advances)
{
if(*advances >= 60 - *minutes){
(*hours)++;
*minutes = 60 - *minutes + *advances;
}else{
*minutes += *advances;
}
}
advanceTimeInMinutes(&hour, &minute, &50);
Поскольку номер не имеет адреса, это вызовет ошибку
&
не является оператором. Точно так же ни один не *
в списке аргументов вашей функции; в теле это оператор разыменования.
Вы не можете передать буквальное значение в качестве ссылки. Поскольку вы никогда не устанавливаете advance
аргумент, тогда не передавайте его по ссылке, поэтому удалите &
для этого аргумента (и сделайте его const
также (забавно, если вы сделаете аргумент const
тогда вы можете использовать ссылку)).
&
, и последнее предложение категорически противоречит первому, без согласования между ними.