Вы, похоже, очень запутались :) Итак, так:
По сути, указатель - это просто переменная, которая хранит адрес другой переменной.Например, предположим, что у меня есть int
с именем i
, я могу сохранить его адрес в указателе p
:
int i = 23;
int *p = &i; // p has type int* (pointer to int) and stores &i (the address of i)
Если я затем захочу изменить то, на что он указывает (т.е.переменную, адрес которой он хранит), я просто присваиваю *p
- это синтаксис, используемый для обозначения указанной вещи.В этом случае *p
относится к i
.Таким образом:
*p = 9; // sets i to 9 (since *p is i)
Я могу переустановить указатель (т.е. сделать его указателем на что-то другое), просто назначив p
, т.е.
int j = 84;
p = &j; // store j's address in p, overwriting what was there before (i.e. i's address)
*p = 18; // sets j to 18 (since *p is now j)
Сейчасссылка немного отличается.Ссылка создает псевдоним для переменной:
int i = 23;
int& r = i; // r has type int& (reference to int) and refers to i
Обратите внимание, что ссылки могут быть реализованы в терминах указателей (или не могут, особенно когда компилятор начинает оптимизировать вещи), ноэто не имеет значения с точки зрения программирования - для нас здесь важно то, как работает язык.
Если вы хотите изменить упомянутую вещь (например, i
в данном случае), вы просто делаете:
r = 9; // sets i to 9 (since r is an alias for i)
В отличие от указателей, ссылки не могут быть повторно установлены .Как только что показано, присвоение r
меняет то, на что вы ссылаетесь (i
), а не саму ссылку.Кроме того, поскольку ссылки не могут быть повторно установлены, они должны быть инициализированы немедленно.Это не относится к указателям.Другими словами:
int *p; // legal
int& r; // bad
Одно заключительное основное отличие состоит в том, что указатели могут быть NULL
, указывая, что они не указывают ни на что.Это просто означает, что они содержат адрес 0
.Ссылки всегда должны ссылаться на реальный объект.Это различие может быть важным для разработчиков, поскольку они могут затем использовать указатели для реализации типа Maybe, то есть если указатель не равен NULL
, тогда использовать объект-указатель, в противном случае сделать что-то еще.Они не могут делать то же самое со ссылками.
Надеюсь, что это ясно в отношении указателей и ссылок!
Теперь, что касается вашего operator+
- цель добавленияОператор должен добавить два объекта и вернуть новый объект, представляющий их сумму.Поэтому, если бы у меня был двухмерный векторный тип, я мог бы написать для него operator+
следующим образом:
Vec2 operator+(const Vec2& lhs, const Vec2& rhs)
{
return Vec2(lhs.x+rhs.x, lhs.y+rhs.y);
}
В своем коде вы пытаетесь вернуть локальный объект toreturn
по ссылке - этоне работает, потому что toreturn
перестает существовать в конце оператора.Вместо этого вы должны вернуться по значению здесь.Между прочим, вы столкнетесь с той же проблемой, если попытаетесь вернуть указатель, например
Vec2* operator+(const Vec2& lhs, const Vec2& rhs)
{
Vec2 result(lhs.x+rhs.x, lhs.y+rhs.y);
return &result; // bad!
}
В этом коде result
перестает существовать в конце оператора, поэтому возвращаемый вами указатель завершитсявверх, указывая на неверное местоположение.Итог - не пытайтесь делать что-нибудь причудливое, возвращайте по значению в такой ситуации.