Могу ли я получить ELI5 для ссылок и указателей и когда их использовать? - PullRequest
1 голос
/ 16 июня 2020

Я уже довольно давно изучаю кодирование, но до сих пор не могу понять ссылки и указатели. Каждый ответ, который я искал, слишком сложен для меня.

Когда мы вызываем переменную для использования, например

int32 y = 1;
int32 x = 2;
int32 z = y + x;

1) Что именно происходит в "z" "? Он вызывает "y" и "x" по ссылке, по указателю или просто по переменной?

В этом коде я сейчас изучаю

FString Log = TEXT("Hello");
FString* PrtLog = &Log;
Log.Len();
(*PrtLog).Len();
PrtLog->Len();

2) Что происходит Здесь? "PrtLog" - это ссылка или указатель?

3) Лектор сказал, что * PrtLog «разыменовывает» PrtLog. Означает ли это, что ссылка на PrtLog удалена? В чем разница между * и ->

4) Зачем нам вообще нужна ссылка или указатель, если вызов переменной так же хорош?

5) Почему некоторые люди заявляют, что 90% переменных будут использовать ссылки и указатели на более высоких уровнях? Насколько они полезны? Если мы просто вызываем по переменной, разве это не проще и быстрее?

Извините, если это слишком много вопросов. Я не могу получить ответ, который могу понять где угодно по ссылкам и указателям, поэтому я действительно запутался.

Ответы [ 3 ]

3 голосов
/ 16 июня 2020

1) Что именно происходит в «z»? Вызов «y» и «x» по ссылке, по указателю или просто по переменной?

Ни одна из этих переменных не является указателем или ссылками. Они всего лишь ... переменные. x и y - используемые переменные. operator+(x, y).

2) Что здесь происходит? "PrtLog" - ссылка или указатель?

PrtLog - это указатель, вы можете увидеть это, посмотрев на объявление его типа:

FString*

Очевидно, что это указатель на FString.

Путаница может возникнуть из-за = &Log;. В этой части кода & - оператор адресации, необходимый для получения указателя на Log. & означает ссылку, только если это часть типа, Log здесь переменная, а не тип.

3) Лектор сказал, что * PrtLog «разыменовывает» PrtLog. Означает ли это, что ссылка на PrtLog удалена? В чем разница между * и ->

В данном случае разыменование - неудачное имя, оно означает получение «вещи», на которую указывает указатель. A FString* - это указатель, указывающий на FString, поэтому разыменование такого указателя приведет к FString.

Разница между * и -> в том, что -> - это сокращение для : (*pointer). или «Разыменовать pointer и получить доступ к его члену».

4) Зачем нам вообще нужна ссылка или указатель, если вызов переменной так же хорош?

Есть несколько возможных причин, по которым вы захотите использовать указатель или ссылку. Например, чтобы ссылаться на объект, но не копировать сам объект.

5) Почему некоторые люди утверждают, что 90% переменных будут использовать ссылки и указатели на более высоких уровнях? Полезны ли они каким-либо образом? Если мы просто вызываем по переменной, разве это не проще и быстрее?

Кто утверждает это? У меня нет цифр, но это не кажется точным. Конечно, это обе очень полезные конструкции, но во многом зависит от проекта, используются ли они в этих числах.

2 голосов
/ 17 июня 2020

x и y называются выражениями lvalue (обычно сокращается до lvalues ​​). Это означает, что они соответствуют ячейкам памяти. Контекст выражения определяет, будет ли значение записано в ячейку памяти или значение извлечено из ячейки памяти.

В коде x = 2; тогда значение записывается в ячейку с именем x . В коде x + 2 значение считывается из местоположения с именем x.

PrtLog является указателем, поскольку оно было объявлено с помощью декларатора указателя. Ответ на вопрос, зачем кому-то использовать указатели, дается здесь: Почему используются указатели?

«разыменование» означает удаление уровня косвенности из выражения указателя. Указатель указывает на ячейку памяти. Результатом разыменования указателя является выражение lvalue, соответствующее этой ячейке памяти. У этого может быть несколько уровней. a->b эквивалентно (*a).b, если a является указателем.

0 голосов
/ 16 июня 2020

Указатель - это просто число. Это число соответствует тому, где в оперативной памяти вашего компьютера хранится значение соответствующей переменной.

int theAnswer = 42;
int *pointer = &theAnswer;

std::cout << pointer << '\n';
/*
 * this will print where in memory `theAnswer` is stored,
 * it'll just look like some random number. Try it out!
 */

Итак, в вашем примере (2) PrtLog является указателем. Ссылка также является указателем, но C ++ как бы «скрывает» ее.

(3) Помните, что указатель - это просто число. Поэтому, если вы хотите работать со значением указателя, а не выполнять математические вычисления с самим указателем (чего делать не следует ig), вам нужно каким-то образом «проследить» за этим числом до места, где хранится значение. Это то, что делает разыменование. Он «следует» за указателем, чтобы получить его значение, и позволяет вам делать такие вещи, как вызывать функции или изменять его.

// make an integer variable
int theAnswer = 42;
int *pointer = &theAnswer;

std::cout << "Original: " << theAnswer << " Pointer: " << *pointer << '\n';
// prints "Original: 42 Pointer 42"
*pointer = 41;
std::cout << "Original: " << theAnswer << " Pointer: " << *pointer << '\n';
// prints "Original: 41 Pointer 41"

(4) Иногда вы просто не можете получить доступ к оригиналу, как с выделение памяти во время выполнения или, если вы хотите создать метод для изменения переменной, et c. В C ++ многое из этого скрыто в стандартной библиотеке с такими вещами, как ссылки и классы, но иногда это все же появляется. Хотя, если вы работаете с необработанными указателями (в отличие от ссылок или классов RAII) в C ++, у вас должна быть веская причина для этого, утечка памяти очень проста.

// you can only access this variable though the pointer
int *dynamic = new int;
*dynamic = 42;

std::cout << *dynamic << '\n';

delete dynamic;

(5) Кажется, это тот же вопрос, что и 4, но я могу интерпретировать его неправильно.

Надеюсь, это ясно. Если у вас есть другие вопросы, не стесняйтесь комментировать, и я постараюсь ответить на них изо всех сил, я буду рад помочь другому Бенджамину!

...