В чем разница между ссылкой и указателем? - PullRequest
1 голос
/ 26 ноября 2010

Может ли кто-нибудь объяснить мне эту разницу очень маленькими словами?Я никогда не понимал этого и очень запутался в своем текущем проекте.То, что я пытаюсь сделать, это исправить этот код:

const Multinumber& Pairs::operator+(const Multinumber &rhs) const
{
    const Pairs &_rhs = dynamic_cast<const Pairs &>(rhs);
    Pairs toreturn(_rhs.X_value+X_value,_rhs.Y_value+Y_value);
    return toreturn; //reference to local variable? fix this?
}

Теперь мой компилятор говорит мне, что это ссылка на локальную переменную, но он не позволит мне превратить возврат в указатель, потому чточем-то отличаются от ссылок.И затем, я также работаю над классом множеств, который должен содержать ссылки или указатели на объекты абстрактного класса.Я полностью сбит с толку.Любая помощь будет высоко ценится.

Ответы [ 3 ]

2 голосов
/ 26 ноября 2010

Во-первых, ваша подпись неверна.Должно быть:

Multinumber Pairs::operator+(const Multinumber &rhs) const;

operator+ должно возвращать новый объект, а не ссылку на любой из аргументов.

Что касается разницы между ссылками и указателями, этот подробный вопрос прямо здесь, на SO.Он охватывает все основы, а некоторые.

1 голос
/ 26 ноября 2010

Вы, похоже, очень запутались :) Итак, так:

По сути, указатель - это просто переменная, которая хранит адрес другой переменной.Например, предположим, что у меня есть 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 перестает существовать в конце оператора, поэтому возвращаемый вами указатель завершитсявверх, указывая на неверное местоположение.Итог - не пытайтесь делать что-нибудь причудливое, возвращайте по значению в такой ситуации.

0 голосов
/ 26 ноября 2010

Указатель имеет некоторый адрес, где находится объект.И ссылка как псевдоним для указателя, и это означает, что вам не нужно разыменовывать его.Но использование аналогично - не копируйте объекты, а работайте только с источником.

В качестве локальной переменной у вас есть переменная toreturn, что означает, что компилятор создает деструктор для этого объекта в концеметод.Итак, вы пытаетесь вернуть уничтоженный объект.

...