Understanding Pointers
- Feb 5, 2022
- 6 min read
Hey there! Chances are you came from my Casting post and here to understand pointers at a much more in depth level. This will be a more technical post but should still be beginner friendly! I will be dramatically simplifying some very complex concepts in this post.
This post should be useful for any beginner or intermediate programmer even if you are a blueprint only user. Even in Blueprint it is important to understand what a pointer is.
So lets cover some basics!
What is a Pointer?
In short a pointer is nothing more than a type and an integer. This integer will be the memory address in your memory. The type is how this pointer can access the memory at this address.
You know these as the following:

Or
AActor* MyPointerToAnActor
Understanding Memory
Note: This is a very simplified version
If you have a vague idea of how memory works, you understand that it is more or less a massive complex of storage units. Picture a warehouse with long corridors, doors on each side, each numbered differently in order. 1, 2, 3, 4, 5, etc. In each of these doors is a value. And in this analogy, an object in your code can be broken up into multiple storage containers. For the purpose of this we'll treat each storage unit as a Byte.
This is important to know, because when you instantiate an object, you allocate a series of these containers for it. If an object has properties that take up 10 containers, you have to place it in a place where it has 10 consecutive empty containers. So if 1-3, 5-7, 12-16 and 20 are all in use, your object has to be placed in spaces 21 to 30. This is despite that 4, 8-11, and 17-19 are all empty, cause none of these have enough room.
Lets give this object some definition. Lets say that this is a basic class that inherits from another class which has it's own parent. So we're at the third level of object.
So we have an object that is of ClassC, that inherits from ClassB, that inherits from ClassA.
That means that this object we have created has properties from ClassA, ClassB, and ClassC, not just ClassC
ClassA has a property that takes up 1 storage units. Lets make this a Boolean. ClassB has a property that takes up 4 storage units. Lets make this an Integer.
ClassC has a property that takes up 4 storage units. Lets make this a Float.
That's only 9 storage spaces though, what about the 10th? That is actually the first, placed in the first unit to give some definition to the following 9. We'll just call this an Identifier.
Kay, memory stuff. What about that casting thing?
The memory part is important. Without it the following will be difficult to follow!
Following our simplified memory talk. Lets say we instantiate an object of ClassC and place it into memory location 21-30.
Slot 21 is the Identifier.
Slot 22 is a Boolean.
Slots 23-26 are an integer
Slots 27-30 are a Float.
Now we have a function GetMyObject. This returns back a pointer to the type of ClassA. We don't even know that ClassB or ClassC exists in this function, we're just iterating over some objects that represent as ClassA, we find one and pass it back as a pointer type of ClassA.
Note that this pointer is of Type ClassA, but it's integer value would be 21. As in our Slot 21 where the identifier of our object that is of ClassC lives. This is because ClassC is a ClassA and therefor can be found in that previous function just fine. This also means that we cannot access anything other than Slot22, or functions that are on ClassA. But our other code really needs the Float that is in ClassC. This is where our casting comes in.
Slot 21 Cast to ClassA is Slots 21-22
Slot 21 Cast to ClassB is Slots 21-26
Slot 21 Cast to ClassC is Slots 21-30
This means that if we cast our pointer pointing to slot 21 to a ClassC type, it will give us a new pointer that is pointing at slot 21, but has access from 21 to 30. Similarly if we had cast to ClassB, we would have access to 21 to 26. Note we always have access to the parent class properties here even after casting.
Similarly if we have a ClassV that does not inherit from ClassA, B, or C, and we get a pointer back from our function and we try to cast our ClassA pointer to ClassV, we will get a nullptr, or Invalid Pointer. These pointers are not safe to use. In C++ you will crash your program, in blueprint it will fail silently and simply do nothing but give you an editor warning. This happens whether or nor you have a valid object in slot 21 or not.
Two examples if you Cast and then check validity:
Slot21 is empty, no object lives there. You cast a pointer pointing to Slot21 to ClassV. We now have a ClassV pointer type pointing at Slot21, if you validity check this it will be null. Because there is no identifier there to compare with. Therefor this cannot be a ClassV type.
Slot21 is not empty, it has a ClassC object there in slots 21 to 30. If you get a pointer of any kind that points to Slot21 and cast it to ClassV it will fail, because it will get the identifier in Slot21 and realize that the object living in Slot21 is not a class that ClassV is or inherits from. And therefor accessing this memory as a pointer type to ClassV, despite that there is a valid object there will likely crash your system. So the validity check will return invalid on it to avoid this from happening.
But why is this done?
So now we know how casting works. But why is it so complicated? This is because of how programming works. When we write code, blueprint or written code, we are telling our compiler what we expect from it. It is a cold logical thing that cannot infer what you want and so you have to be explicitly literal with it. It has no feelings or ability to do anything more than process literal and simple facts.
Example1:
Lets take one of the most common cases of casting. GetPlayerCharacter. This returns an ACharacter pointer to the player's currently possessed pawn. The writer of this function has no idea what your classes are that inherit from ACharacter. So they simply made it pass back as a Character type, which leaves it up to you to cast it to your type.
Example2: Bear with me, this is a long example!
Another classic example is distance checking. Only one value is usually required for distance checking actors and that is a Vector that represents the object's location. Lets say you want a function that gets the closest Character to a point. Why Character's? Cause that's what your code needs, function that only checks characters.
You would start by writing a function that passes an array of character pointers, and a vector location and returns a single character pointer. Iterate over the array of Characters, call GetActorLocation on them and do your distance check, save the closest, then return it at the end of the loop. Simple.
But now you have a new requirement a few weeks later where you need the closest Actor to a point. Well you can't use the character one cause it doesn't allow other actor types, you start by writing a function that takes in an array of Actors and an FVector location, You write your loop, save the closest... This is familiar. Hmm.. whatever, return the closest Projectile. Done.
Couple of weeks later you need a function that gets the closets SceneComponent on an actor to a location. So.. You start writing your function, takes in an array of SceneComponents, takes a Vector Location, you do your loop, you find the closest scene component to the point, and you return it.
You should realize by now that you've repeated yourself twice. You have three basically identical functions here. Now, having these three functions is perfectly fine. You don't need to delete them. Keep them! But the trick is that only one of these really needs to do any actual processing and that is the one with the most basic component.
Lets start at the basics. ACharacter is an AActor. AActor has the GetActorLocation function that gets both your Character and Actor's locations. All this call does is returns the Actor or Character's RootComponent's world location. You see where this is going yet?
The only distance checking function you really need is for SceneComponents. A simple function that takes in an array of SceneComponents and a location, distance checks them and then returns the closest SceneComponent.
Now, you just need to rewrite your other two functions to do something very simple. Make an array of ActorComponents, get all root components of your characters or actors, then pass them into this component distance checking function. Then simply get the owner of the component returned, and cast it to Actor or Character. You have now written much less code and have not repeated yourself.
Thank you for reading!
If this was of interest, be sure to check out my post on


Comments