I will use example with this simple structure. We will asume that size of int is 4 bytes - this structure will have 8 bytes in size.
struct Point {
int x;
int y;
Point(char x, int y){
this->x = x;
this->y = y;
}
}
Now we will create 2 variables inside our nice function. One will be normal variable , another will be pointer
void niceFunction(){
Point normalVariable(10, 5);
Point* pointer = new Point(10, 5);
}
niceFunction(); // we call our function
What is difference ?
First variable contains our whole structure. If you use sizeof(normalVariable)
, you will get 8 bytes as result.
Second contains address to our structure. When you use sizeof(pointer)
you will get 4 bytes - our structure is somewhere in dynamic memory and this pointer only contain address to our structure.
Allocation
Allocation is act when we request memory for our structure. System must find free memory and give it to us. We will fill this memory with our stuff (in our cases , we use numbers 10 and 5).
In first case (normal variable) , allocation is faster , because system use stack for normal variables and thus knows where your stuff is stored and where is free area. This has one problem - stack has limited size and if you allocate to many structures in it , memory will be depleted and your program will be terminated by os - error called Stack Overflow
In second case (pointer), system must find free area in dynamic memory and inject your structure there. This takes some time. Also you have unlimited memory (you are limited only by size of your ram memory and restrictions that are from operating system)
Dealocation
Dealocation is act of returning memory to system. Returned memory will be resued again when needed
In first case , dealocation is automatical. Because local variables exist only inside of function , there isn't any reason to dealocate them from stack once our function ends.
In second case (pointer), our structure is somewhere in memory and thus system cannot know how to dealocate it. We must explicitly state that we want to dealocate our structure
void niceFunction(){
Point normalVariable(10, 5);
Point* pointer = new Point(10, 5);
delete pointer; // this will dealocate our structure
}
If we forget to dealocate structure in dynamic memory , it will stay here until end of the program.
Argument passing / Copying
Imagine function that will have 2 parameters (point a and b) and it will return you their distance. We will use normal variables in first and pointer in second.
float distanceNormal(Point a, Point b){
// body of function is irelevant for us
}
float distancePointer(Point* a, Point* b){
// body of function is irelevant for us
}
In first case , when we pass our points into function , system will copy them. That means it will allocate new memory in stack inside function and it will copy your whole structure into that allocated memory. This can be inefective if your structures are massive or if their constructor is doing expensive operations. This also means that two normal variables cannot share one structure - they can have same values , but they are not same structure.
In second case, nothing is copied. Instead, system will only pass address to your structure in dynamic memory. This also lead to one effect - when you modify structure using pointer. It will change original structure , because they are both have same address
Point* pointer = new Point(10, 5); // values of our point are (10, 5)
void changeX(Point* point){
point->x = 50;
}
changeX(pointer); // after this call, values of our point are (50, 5)
This is exploited by methods of structures/objects. Do you see that weird variable called this in constructor? That is also pointer* - it is pointer to our structure. This allows us manipulate values of structure directly.
Conclusion
You can see that both of them have advantages and disantvantages. When to use them ?
Use normal variables when:
you don't use its content outside of function. When you have something that is used only inside of function , there isn't any reason to allocate it in dynamic memory. Stack is better option for this
you want automatic dealocation: in our case , normal variable will be dealocated automaticaly. Second one(pointer) must be dealocated manualy.
you don't want share it into function: When you use pointer, you are working with original and changes will be aplied to original. When you use normal variable, you are working with copy and original structure will be unaffected
Use pointers when:
- you want to work with original: if you want to manipulate original structure inside function, use pointer.
- you want to avoid copying: if you have structure and you have function that is called 1000 times, it is ineffective to use normal variable. Use pointer to avoid copying.
- you want to avoid automatic allocation: sometimes , automatic allocation isn't good. Like you allocated structure for your game that has hundreds of bytes and after end of function , it will be dealocated. This never happend with pointers , you must dealocate them manualy using delete.
Golden rule is: Use normal variables where you can, use pointers where you must