Pointers has always made such a pain in my head. I will try to explain it in a manner that it no more remains a pain.

What is a pointer?

To put it simply, its a variable which holds a memory address. Computer memory is divided into sequentially numbered memory locations. Different computer architecture use different schemes to number these locations, and usually we don’t need to care about these details as they are taken care of by compilers. We can however access these address by using address of operator (&). Ex:

unsigned short some_var = 5;   // some variable defined
std::cout<<"value of some_var="<<some_var<<endl; // yields value stored in the variable
std::cout<<"address of some_var="<<&some_var;<<endl // yields address of the stored variable

The first print will yield the value stored in some_var (5). While the second one will display the address of the variable, which would look something like 0x8fc9:fff8, depending on your machine.

Next important operator in this pointer business is the de-referencing operator (*). This operator is used to retrieve value stored at some address. Continuing with our example:

unsigned short some_var = 5;   // some variable defined
std::cout<<"value of some_var="<<some_var<<endl; // yields value stored in the variable
std::cout<<"address of some_var="<<&some_var;<<endl // yields address of the stored variable
// going further and illustrating the dereferencing operator *
int* pVar = 0;
pVar =  &some_var;
std::cout<<"This is the dereferenced retrieval of pVar"<<*pVar;

Here we have defined a pointer variable which will point to some integral value, that’s why its “int* pVar”. Initially its been initialized to zero. A pointer initialized to zero is called as null pointer.

Next we assigned “pVar” with address of “some_var” by using address operator “&”.

Finally, we went to address stored by “pVar” pointer and accessed the value mentioned on that address by using the dereferencing operator (*). This example will ultimately print value stored by “some_var” because this variable was referenced by “pVar” in very first place.

Now, we will address the question:

Why to use pointer ?

Pointers are used, most often, for three tasks:
●  Managing data on the free store.
●  Accessing class member data and functions.
●  Passing variables by reference to functions.

What’s free store?

There are five areas of memory:

  • Global name space : where global variable resides
  • The stack : where local variables resides
  • Code space: where code exists
  • Registers: used for internal housekeeping functions, such as keeping track of the top of stack
  • The free store: All about remaining memory is given to free store

The problem with local variable is that they don’t persist after function returns, whereas global variable are insecure to use, although they offer global scope. Free store solves this dilemma by providing addressable memories. By writing addressable I mean that only those with proper address would be able to able to access the content of corresponding memory.

The advantage to the free store is that the memory you reserve remains available until you explicitly free it.You allocate memory on the free store in C++ by using the new keyword. new is followed by the type of the object that you want to allocate so that the compiler knows how much memory is required. Example:

unsigned short int* pVar;
pVar = new unsigned short int;

This can also be written as:

unsigned short int* pVar = new unsigned short int;

In either case a free store memory of two bytes will be pointed by pVar. This is how we can access the pointed memory location:

*pVar = 75;

This essentially instructs to put 75 in the memory location pointed out by “pVar” pointer.

Note: If new cannot create memory on the free store (memory is, after all, a limited resource) it returns the null pointer. You must check your pointer for null each time you request new memory.

Freeing the free store:

The memory allotted in free store is not automatically relieved until the program ends. Consider a situation in which a pointer is declared inside some function. When this function returns the pointer also goes out of scope like other local variables. If the pointer had been pointing to some value in free store – that space gets locked until the program ends. This causes memory leak – because even though memory is available, it don’t appears if it is actually. Thus, we use delete exclusively to free up the registered memory. Example (continuing previous example):

delete pVar;

WARNING: When you call delete on a pointer, the memory it points to is freed. Calling
delete on that pointer again will crash your program! When you delete a pointer, set it to zero (null). Calling delete on a null pointer is guaranteed to be safe. For example:

int* pVar = new int;
delete pVar; // frees up the memory
pVar = 0; // sets pointer to null .... delete pVar is harmless now

Leaks…Leaks!!

Another way we might create memory leak is by reassigning our pointer before deleting it. Ex:

int* var = new int;
*var = 23;
var = new int; // will cause leak
*var = 45;

This should have been written as:

int* var = new int;
*var = 23;
delete var;
var = new int; // will cause leak
*var = 45;

NOTE: For every time in your program that you call new, there should be a call to delete. It
is important to keep track of which pointer owns an area of memory and to ensure that the
memory is returned to the free store when you are done with it.

Objects on free store:

Just as you can create a pointer to an integer, you can create a pointer to any object. If you have declared an object of type “Tool”, you can declare a pointer to that class and instantiate a “Tool” object on the free store, just as you can make one on the stack. The syntax is the same as for integers:

Tool* pTool = new Tool;

This calls the default constructor of “Tool” that takes no parameter.

Deleting objects from free store:

When you call delete on a pointer to an object on the free store, that object’s destructor is called before the memory is released. Example:

#include <iostream>

class Tool
{
    public:
        Tool(); // constructor
        ~Tool(); // destructor
    private:
        bool is_rusty; // boolean datatype
};

Tool::Tool() // defining for Tool class constructor
{
    std::cout<<"Called constructor\n";
    is_rusty=true;
}

Tool::~Tool() // defining destructor for Tool class
{
    std::cout<<"Called destructor\n";
    if (is_rusty==true)
{
    std::cout<<"Your tool is rusty:"<<"Yes";
}
}

int main()
{
    Tool* pTool = new Tool;
    delete pTool;
}

Output:

Called constructor
Called destructor
Your tool is rusty:Yes

 

Accessing data members:

You accessed data members and functions by using the dot (.) operator for Tool objects created locally. To access the Tool object on the free store, you must dereference the pointer and call the dot operator on the object pointed to by the pointer. Therefore, to access the GetInfo member function, you would write:

(*pTool).GetInfo();

As it is a bit lengthy, c++ provisions “->” operator to access member of objects from free store:

pTool->GetInfo();

will produce equivalent results.

Note: Much of the content is my articulation of content from “Sams Teach Yourself C++“. I am putting here those portions which are relevant to my project. If you really want to learn the language then support its author by purchasing your own copy. Its really worth purchasing it.