Pointer

8 minute read

What is a pointer?

In general of C++ and C, we initialize a variable as:

int var = 10;

This will have a variable called var with a value 10 stored in. What happens inside is that it will first reserve space for an integer and then assign 10 to that memoty block. If we want to know the address of the memory, we should do

&var

This will give you the address of var. However, this is inconvenient if we want to share the value in var with someone else in which we have to copy the value every time that we want to share. The simple way is to share the address of that variable.

Pointer is the variable to hold the address of a variable.

How to use a pointer?

you can initialize a pointer in c++ based on the format:

typeName* ptr;
typeName* ptr = new typeName();

Either way works. For example, we can have:

int* ptr;
int* ptr = new int();

What happens here is that we just initialize an int type pointer, which is the address of a memory block on stack. We haven’t assigned any value to that memory. To assign a value:

*p = 10;
std::cout << *p << "\n";

By using the asterisk sign, we can access the content on the memory block. We can then print the value in console, which outputs 10 in this case.

What happens at backend can be visualized by:

Pointer Demo

How to intialize an object pointer?

Object pointer is basically a pointer that points to an object. The initialization is similar in this case.

Foo* ptr = new Foo ();
Foo* ptr2 = new Foo;

Both will create an object of class Foo in heap (dynamic memory). Ptr or ptr2 will point to that object. If Foo is a Plain Old Data, this will automatically intialize to some random vlaue. Common POD variable type is int, float, double and etc. in c++.

Note that this is different to :

Foo foo;
Foo foo = Foo::Foo();

Both will jsut create a foo object of Foo type in automatic memory block using default constructor. The memory is released once the object goes out of scope.

Pointer scope

Imagine that in a function, we have:

Foo* ptr = new Foo();

When function exits, the ptr will be gone from stack automatically. However, the object that ptr points to will stay on heap and become bad memory. You have no chance to delete them. This is sometimes called memory leaks issue.

Memory leaks

In C or C++, if you allocate some space in memory, you are responsible for releasing the memory once it is done. Otherwise, it will create memory leaks. That is, no one is able to access to that memroy in the duration of program anymore. It becomes bad memory.

Thus, we should delete our pointer after we are done with it. For example, we can do:

int *ptr = new int(10);
delete myPointer; 
// Then do something else
*myPointer = 11; 

Note that we should first delete pointer contents and then we can do something else with it.

Let’s look at some bad examples:

Bar* bar = new Bar ( *new Foo() );
Bar* bar2 = new Bar ( *new Foo );

Both are bad examples because the initialized pointers in the bracket are not deleted and cannot be deleted anymore. Then, we have memory leaks.

The correct way to do it is:

Bar* bar = new Bar ( Foo::Foo() );
Bar* bar = new Bar ( new Foo() );

Both are valid syntax and will not cause memory leaks.

Note that in C++, we can use smart pointers to avoid from memory leaks.

Reference and pointer

In C++, reference and pointer are very similar. Many people are confused about the difference. In general,

Pointer: is a varaible that stores the memory address of another variable.

Reference: is an alias or nick name of a existing variable. It also stores the address of another variable.

The key difference between the two is :

1) You cannot have NULL reference whereas you can have a pointer to point NULL. And it cannot be void.

2) Once reference is initialized to an object, it cannot be changed. On the other hand, pointer can be changed whatsoever.

3) There is a concept of pointer of pointer whereas there is not such a thing on reference.

4) There is pointer arithmetic whereas there is no such thing on reference.

When to use what

The performance is very similar. But in general:

1) We use reference to pass parameter in function and return from function as well.

2) We use pointer to implement data structure like linked list, tree and etc. and if we need to pass null pointer to the function.

Example

We can have an example here:

#include<iostream> 
using namespace std; 
  
int main() 
{ 
  int x = 10; 
  
  // ref is a reference to x. 
  int& ref = x; 
  
  // Value of x is now changed to 20 
  ref = 20; 
  cout << "x = " << x << endl ; //output 20
  
  // Value of x is now changed to 30 
  x = 30; 
  cout << "ref = " << ref << endl ; //output 30
  
  return 0; 
}