1

I've been learning coding for quite a while now but still cannot understand References and Pointers. Every answer I've searched is way too complicated for me.

When we're calling a variable to be used, for example

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

1) What exactly is happening in "z"? Is it calling "y" and "x" by reference, by pointer or just calling them by variable?

In this code I'm currently learning

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

2) What is going on here? Is "PrtLog" a reference or a pointer?

3) The lecturer said *PrtLog is "dereferencing" PrtLog. Does that mean the reference for PrtLog is removed? Whats the difference between * and ->

4) Why do we even need a reference or a pointer if calling a variable is just as fine?

5) Why do some people claim 90% of variables will be using references and pointers in higher levels? Are they beneficial in any way? If we just call by variable, isn't it simpler and faster?

Sorry if this is too many questions. I can't get an answer I'm able to understand anywhere on references and pointers so I'm really confused.

Benjamin
  • 39
  • 5
  • Variables don't get "called". Only functions do. I don't know what you mean by "Is it calling "y" and "x" by reference, by pointer or just calling them by variable?" – eesiraed Jun 16 '20 at 19:28
  • `PrtLog` is a pointer. It's a bit unfortunate that dereferencing is named that way, because it has nothing to do with references. You can only dereference pointers. – alain Jun 16 '20 at 19:45
  • @BessieTheCow I have absolutely no idea too haha. That was what the lecturer was saying. Or maybe I just heard wrong since there's too much info. What is the correct term though? Fetching data from y and x? Getting data? Edit: It may have been called "Passing". There's just too many terms in coding I'm getting really swamped – Benjamin Jun 16 '20 at 19:53

3 Answers3

4

1) What exactly is happening in "z"? Is it calling "y" and "x" by reference, by pointer or just calling them by variable?

None of those variables are pointer or references. They're just..variables. x and y are used variables. operator+(x, y).

2) What is going on here? Is "PrtLog" a reference or a pointer?

PrtLog is a pointer, you can see this by looking at its type declaration:

FString*

Clearly it's a pointer to a FString.

The confusion might arise because of the = &Log;. In this part of the code & is the address-of operator required to get a pointer to Log. & only means reference when it's part of a type, Log here is a variable, not a type.

3) The lecturer said *PrtLog is "dereferencing" PrtLog. Does that mean the reference for PrtLog is removed? Whats the difference between * and ->

Dereferencing is just an unfortunate name in this case, it means to get the "thing" that the pointer is pointing to. A FString* is a pointer pointing to a FString so dereferencing such a pointer would yield a FString.

The difference between * and -> is that -> is a shorthand for : (*pointer)., or "Dereference pointer and access its member`.

4) Why do we even need a reference or a pointer if calling a variable is just as fine?

There are a few possible reasons you'd want to use a pointer or a reference. For example, to refer to an object but not copy the object itself.

5) Why do some people claim 90% of variables will be using references and pointers in higher levels? Are they beneficial in any way? If we just call by variable, isn't it simpler and faster?

Who claims this? I don't have the numbers but this doesn't seem accurate. Surely they're both very useful constructs but it very much depends on the project if they're used in those numbers.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
  • 1) Thanks for the reply, its getting clearer by the minute from the replies but right now it is still a little cloudy. Correct me if I'm wrong; what I got was Reference means the location where my variable is stored. So if I declare {int32 x = 5}, the number 5 is stored somewhere and the location is some random HEX number like 123f43. The HEX number is called an address, right? So if I Reference int32& y = x, y will be 123f43, right? – Benjamin Jun 16 '20 at 20:08
  • @Benjamin That's not fully correct, that'd be true for a pointer. A pointer holds the address to the variable it's pointing to. What an address looks like is not really a concern here and you shouldn't focus too much on the details of it. Remember, as far as the language is concerned only a pointer's value contains the address of where it's pointing to, a reference does not. For the language, a reference (`&` not `*`) doesn't have an address, it just always directs you to what variable it's bound to. – Hatted Rooster Jun 16 '20 at 20:11
  • 2) And pointer is a the complete opposite of reference? Using the above example, if I code {int32* z = y} I should get z = 5, which is what x is supposed to be. And since y is the "location" of x, z will return me the number stored in location 123f43, right? – Benjamin Jun 16 '20 at 20:12
  • @Benjamin No, a pointer is kind of like a reference. They just have a few differences to make references more safe. https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in this answer might answer that for you in more detail. They're definitely not the opposites. – Hatted Rooster Jun 16 '20 at 20:14
  • Im so sorry for being an annoyance, but in the link above, starting from point 2 onwards Im completely lost. What exactly is a pointer and what exactly is a reference, and lastly what exactly is a variable? Why do they sound so similar in definition but so different at the same time? Edit: At my level of game making in Unreal Engine C++, do I really need to use Pointers and References? I really want to avoid them as much as I can if possible – Benjamin Jun 16 '20 at 20:21
  • Oh, I forgot to reply to the last question in 5). Whilst searching in StackOverflow for answers on Pointers and References, I saw a reply saying in high level programming, References and Pointers are significantly more used than passing Variables here and there. Apparently they decrease load on CPU and RAM or something. So the fella claimed that 90% of the time, variables is replaced with pointers and references. – Benjamin Jun 16 '20 at 20:25
  • Nitpicking here but dereferncing `T*` usually yields `T&` – Sebastian Hoffmann Jun 16 '20 at 20:29
  • @Benjamin Usually references are implemented by pointers. E.g if you have a struct which holds a `T& m_member;` it will always surely be stored internally as a pointer. Every object resides somewhere in *memory* and a pointer is just a variable holding a *memory address*, i.e an integer which *points* to the location where some object resides. A reference is basically the same, just that the pointer syntax is hidden from you and there are some other restrictions: References can never be null and they can't be set to a different value. – Sebastian Hoffmann Jun 16 '20 at 20:37
  • @Benjamin Whether to use a reference or a pointer depends on the context and on semantics: Pointers either imply that im directly working with memory (e.g a `unsigned char*` to denote a buffer), the value can be missing or is assumed to residing on the heap and someone has to manage it. References on the other hand imply that its the callers responsibility to care about all these things. The callee just want to get a valid reference to something which the language guarantees for him (as references can never be null). – Sebastian Hoffmann Jun 16 '20 at 20:42
  • @Benjamin To clarify last point: A function `int* foo()` which returns a pointer implies one of the following: 1) The result can be missing, 2) The result is an actual memory address and should be interpreted as such, 3) The result is a newly allocated object (/int) and someone has to assume ownership. On the other hand, a function `int& foo()`says: "Im always returning an integer and it will stay valid as long as myself stays valid. You dont have to care about ownership, I own it and i will care for it". – Sebastian Hoffmann Jun 16 '20 at 20:45
  • @Benjamin So why would you want to return an `int&` instead of `int`? For starters: it allows the caller to modify the underlying value, i.e `foo() = 42` would set the value to 42. Also, in the real world you are usually not returning an int but `SomeReallyBigType`. Returning it **by value**, i.e `SomeReallyBigType foo()` will result in a copy which is usually expensive. Instead you return **by reference**, i.e `SomeReallyBigType& foo()` to alleviate the copy. – Sebastian Hoffmann Jun 16 '20 at 20:49
  • `operator+` only exists for class types – M.M Jun 16 '20 at 21:04
  • @SebastianHoffmann dereferencing a `T*` yields an lvalue of type `T`. Expressions don't have reference type – M.M Jun 16 '20 at 21:06
  • @M.M I guess you're right. Yet it holds that `decltype(*p)` is `T&` and not `T`. The answer as I read it seems to imply that `decltype(*p)` is `T`. – Sebastian Hoffmann Jun 16 '20 at 21:15
  • @M.M sure, built in `operator+`. I'm not trying to put in as much detail as I can, rather keep it understandable. – Hatted Rooster Jun 17 '20 at 08:24
  • @SebastianHoffmann omg Thank you so much for the indepth explanation. I think yours is the clearest among here. May I ask you to check if I interpreted it correctly? Basically pointers and references are the same: they hold the address of the data that's stored. And when you want to get the data to use it somewhere, they direct it to you rather than copying and using another memory space. At my level where Im at, Im using small data types, so pointers and reference are not of a significance. But as you've said, `SomeReallyBigType` cant afford to be copied and pasted. – Benjamin Jun 17 '20 at 09:44
  • @SebastianHoffmann So that's where pointers and references comes in. And the difference between pointers and references is that pointers can be set to different value (modified I assume?) and references is permanent. I've some extra questions I'd like to ask, so Im wondering if you would tolerate it? – Benjamin Jun 17 '20 at 09:47
  • @Benjamin Yes you're correct so far. Only a slight technicality: It's unspecified whether references have storage or not (see https://stackoverflow.com/questions/26631169/why-does-sizeof-a-reference-type-give-you-the-sizeof-the-type as well). Usually they have and are the same as a pointer, but if you e.g just take a reference to an local `int` the compiler will almost definitely just use the same register. Another typical usecase for pointers is dynamic storage, e.g you would typically see something like `char* buf = new char[10000]` to allocate 10kb of storage. – Sebastian Hoffmann Jun 17 '20 at 09:56
  • @SebastianHoffmann By the way, Im pretty sure I was too tired after pulling an all nighter. I re looked at my course and the lecturer clearly stated `FString* PrtLog = &Log;` means we are pointing to the **address of** Log. The ampersand was just there to mess me up into thinking its pointing to reference of Log XD – Benjamin Jun 17 '20 at 09:58
  • @Benjamin Raw pointers have become kind of rare though in modern cpp. You are more likely to encounter so called "smart" pointers, e.g `std::auto_ptr` and `std::unqiue_ptr` (https://en.cppreference.com/w/cpp/memory/unique_ptr). I don't think that this is of any concern to you right now but just keep it in mind that if you encounter a raw pointer its usually either used on purpose or just bad/old code. – Sebastian Hoffmann Jun 17 '20 at 09:58
  • @SebastianHoffmann Non-owning raw pointers are still more than fine. – Hatted Rooster Jun 17 '20 at 12:27
2

x and y are called lvalue expressions (usually shortened to lvalues). That means they correspond to memory locations. The context of the expression determines whether a value is written to the memory location, or a value retrieved from the memory location.

In the code x = 2; then a value is written to the location named by x. In the code x + 2, a value is read from the location named by x.

PrtLog is a pointer because it was declared with a pointer declarator . The question of why someone would use pointers is answered here: Why use pointers?

"dereference" means removing a level of indirection from a pointer expression. A pointer points to a memory location. The result of dereferencing a pointer is an lvalue expression corresponding to that memory location. There can be multiple levels of this. a->b is equivalent to (*a).b if a is a pointer.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

A pointer is just a number. This number corresponds to where in your computer's RAM the value of the corresponding variable is stored.

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!
 */

So in your example, (2) PrtLog is a pointer. A reference is also a pointer, but C++ sort of 'hides' that it is one.

(3) Remember that a pointer is just a number. So if you want to work with the pointer's value, as opposed to doing math with the pointer itself (which you shouldn't do i.g.), you need to somehow 'follow' that number to where the value is stored. This is what dereferencing does. It 'follows' the pointer to get its value, and allows you to do things like call functions or modify it.

// 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) Sometimes you just can't get access to the original, like with runtime memory allocation, or if you want to make a method to mutate a variable, etc. In c++ a lot of this is hidden in the standard library with things like references and classes, but it does still come up occasionally. Although, if you're working with raw pointers (as opposed to references or RAII classes) in C++, you should have a good reason for doing so, leaking memory is really easy.

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

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

delete dynamic;

(5) This seems to be the same question as 4, but I may be interpreting it wrong.

I hope that's clear. If you have any other questions feel free to comment and I'll try my best to answer them, I'd be happy to help a fellow Benjamin out!

  • Thanks for the reply. I want to clarify because I realized I don't know what Pointers, References and Variables really mean after the answer on top of yours. `*` means pointer, `&` means reference and variable is just a word/letter you define and give it some meaning, like a letter `5` or the word `dog` right? In this line of code:`int *pointer = &theAnswer;` why did you put both `*` and `&` in? I feel really bad for constantly repeating my question but I'm too confused with this and really would like to understand. Im so sorry – Benjamin Jun 16 '20 at 20:32
  • @Benjamin `int* pointer` declares a variable named `pointer` of type `int*`, i.e an int pointer. `int& ref` declares a variable named `ref` of type `int&`, i.e an int reference. `&theAnswer` gets the address of `theAnswer`, i.e a value of type `int*`. The use of `&` in both cases is not related to each other. `&` has a different meaning in both contexes. The `&` in `&theAnswer` is called the **address-of operator** or `operator&` (https://en.cppreference.com/w/cpp/language/operator_member_access#Built-in_address-of_operator) – Sebastian Hoffmann Jun 16 '20 at 20:57