В чем разница? Потому что это:
int Value = 50;
int *pValue = &Value;
*pValue = 88;
и ref version делают то же самое:
int Value = 50;
int &rValue = Value;
rValue = 88;
Какой из них лучше использовать? Спасибо.
В чем разница? Потому что это:
int Value = 50;
int *pValue = &Value;
*pValue = 88;
и ref version делают то же самое:
int Value = 50;
int &rValue = Value;
rValue = 88;
Какой из них лучше использовать? Спасибо.
В этом случае они эквивалентны.
Неважно, что вы используете, и ни один из них не является "лучшим".
Если вы действительно хотите выбрать между ними, то ссылка, вероятно, более идиоматична. Я вообще придерживаюсь ссылок везде, где могу, потому что мне нравится OCD: они чувствуют себя "более жесткими", не могут быть перевязаны (с вами или без вас) и не требуют разыменования для получения значения.
Но я не знаю какого-либо общего согласия по этому вопросу в таких случаях.
Также обратите внимание, что они не могут скомпилироваться с тем же кодом, если ваша реализация не реализует ссылки с указателями, хотя я не знаю такой реализации, и вы все равно не заметили бы разницу.
Указатель - это адрес ячейки памяти. Вы можете изменить значение этого адреса, чтобы указать на разные адреса памяти.
Ссылка - это псевдоним переменной. Вы можете назначить этот псевдоним только во время объявления. Вы не можете изменить, какая переменная ссылается на псевдоним после объявления.
Следующие присваивания указателей невозможны со ссылками.
int a = 10;
int b = 20;
int* pInt = NULL; // A pointer pointing at nothing.
pInt = &a; // pInt now points at a
pInt = &b; // pInt now points at b
Что касается лучшего, все зависит от контекста.
Я использую ссылки для параметров метода и функции.
void updateFoo(Foo& foo)
Я использую ссылки на сложные сложные объекты.
Foo& foo = bar.getBaz().getFoo(); // easy access to foo
Я использую указатели для динамически выделенных объектов.
Foo* pFoo = new Foo();
Я использую указатели для вещей, которые могут указывать на разные значения (в том числе и на отсутствие значения).
Foo* pFoo = NULL;
if (condition1)
pFoo = &foo1;
else (condition2)
pFoo = &foo2;
Как правило, я по умолчанию ссылаюсь на ссылки и использую указатели в тех местах, где ограничения на ссылки вызывают проблемы.
Различия заключаются в следующем:
Ссылка является псевдонимом объекта и имеет тот же адрес, что и объект.
int a; // address of a : 0x0012AB
int &ref = a; // address of ref : 0x0012AB (the same)
Ссылки должны быть инициализированы:
int &ref = a; // GOOD, is compiling
int &ref; // BAd, is not compiling
Указатель - это еще одна переменная, которая содержит адрес:
int a = 5; // address of a : 0x0012AB
int *p = &a; // address of p : 0x0012AF (is different )
// value of a is 5
// value of p is 0x0012AB (address of a)
Указатели могут быть NULL
int *p = NULL;
Мое правило состоит в том, чтобы использовать ссылку или ссылку на const, если не требуется указатель.
Ссылка не может быть пересмотрена, и она синтаксически чиста. Ссылка также гарантирует вам, что ссылка не NULL
.
Я также могу использовать указатель для удобства при использовании массивов.
Я согласен с ответом justin и хочу прояснить его с помощью крошечного примера.
Предположим, вы не совсем помните синтаксис геометрической библиотеки 2D-изображения: это
bool BooleanOr( const Bitmap & input1, const Bitmap & input2, Bitmap * output );
или это
bool BooleanOr( Bitmap * output, const Bitmap & input1, const Bitmap & input2 );
Если в вашей компании все используют указатели на выходы и константные ссылки для входов, практически невозможно сделать ошибку: когда вы видите такие вызовы, как
BooleanOr (thisBitmap, thatBitmap и другойBitmap);
вы сразу же знаете синтаксис.
Отличные ответы здесь. Я хотел бы указать на 2 конкретных использования ссылок: -
Случай 1: При реализации operator[]
. Этот оператор обычно должен возвращать то, что может использоваться как цель назначения. Пример: -
vector<int> v(20);
v[1] = 5; //The target of the assignment is the return value of operator []
Здесь operator []
возвращает ссылку элемента по указанному индексу в vector
. Если бы operator []
был предназначен для возврата указателя на элемент по указанному индексу, то 2-я строка должна была бы быть написана следующим образом: -
*v[1] = 5
Теперь, когда v
выглядит как вектор указателей - это точно не так!! Таким образом, чтобы здравомыслие преобладало - operator []
возвращает ссылку, а не указатель на индексированный элемент в векторе
Случай 2: Нет явной проверки null
, требуемой для ссылок. Некоторые ответы уже говорили об этом - хотелось представить преимущество с помощью фрагмента кода: -
void fun(const int& val)
{
cout << val;
}
void fun(const int* val)
{
if (val){ //Additional overhead with pointers
cout << *val;
}
}