Pointers in C++

When Heap allocation is needed?

  • When we want to have the variable or object across the function calls to modify or edit, we will use heap. 
  • Also, when we want to access the variable across the process until the end of the program, we will go for heap allocation. 
  • When we want to change a data outside of the location where it is declared, we could change the data using pointer and make it persisted beyond the function call. 

In C++, the below two statements define the same.

int *ptr;           // •ptr is an integer to pointer

int* a_ptr;      // a_ptr is a pointer to integer

Size of this pointer depends on the processor, so it could be 32 bit or 64 bit.

In the below statement, both are pointers to an integer. 

int *c_ptr, *b_ptr;   

int* d_ptr, e_ptr; 

In the last statement, e_ptr is just an integer and not a pointer to an integer.  The statement is as same as 

int *d_ptr; int e_ptr;

Pointer Initialisation

Pointers don't initialise themselves. We need to explicitly initialise them. 

Example 1

int i = 10;

int *i_ptr = &i; // This is creating a pointer

Now i_ptr points to variable i; 



Dereferencing a pointer

Dereferencing is reading the data that pointer points to. 

#include <iostream>

int main()
{
   int i = 10;
   int *i_ptr = &i;

   cout << "variable i's value " << i << endl;
   cout << "Address of i " << &i << endl;
   cout << "Address of i " << &i << endl;
   
   int z = 20;
   cout << "Before dereferencing: Variable z's value " << z << endl;
   /* Dereferencing the pointer */
   z = *i_ptr; 

   cout << "After Dereferencing: Variable z's value " << z << endl;
   cout << "variable i's value " << i << endl;
    
   return 0;
}

Output:
1
2
3
4
5
6
variable i's value 10
Address of i 0xff8950e8
Address of i 0xff8950e8
Before dereferencing: Variable z's value 20
After Dereferencing: Variable z's value 10
variable i's value 10

Some Fun with Pointer

#include <iostream>

int main()
{
   int i = 10;
   int *i_ptr = &i;

   cout << "variable i's value " << i << endl;
   cout << "Address of i " << &i << " Address of i_ptr " << i_ptr << endl;
   
   int z = 20;
   cout << "Before dereferencing: Variable z's value " << z << endl;
   /* Dereferencing the pointer */
   z = *i_ptr; 

   cout << "After Dereferencing:" << " Value of z " << z;
   cout << " i " << i << " i_ptr " << *i_ptr << endl;

   *i_ptr = 30;
   cout << "After assigning different value:" << " Value of z " << z;
   cout << " i " << i << " i_ptr " << *i_ptr << endl;

   (*i_ptr)++;
   cout << "After ++ pointer's value:" << " Value of z " << z;
   cout << " i " << i << " i_ptr " << *i_ptr << endl;

   *i_ptr++;
   cout << "After ++ pointer's value without ():" << " Value of z " << z;
   cout << " i " << i << " i_ptr " << *i_ptr << " Address of i_ptr " << i_ptr << endl;

   i_ptr++;
   cout << "After ++ pointer's address" << " Value of z " << z;
   cout << " i " << i << " i_ptr " << *i_ptr << " Address of i_ptr " << i_ptr << endl;

   return 0;
}


Output:
1
2
3
4
5
6
7
8
variable i's value 10
Address of i 0xffa59820 Address of i_ptr 0xffa59820
Before dereferencing: Variable z's value 20
After Dereferencing: Value of z 10 i 10 i_ptr 10
After assigning different value: Value of z 10 i 30 i_ptr 30
After ++ pointer's value: Value of z 10 i 31 i_ptr 31
After ++ pointer's value without (): Value of z 10 i 31 i_ptr -16121856 Address of i_ptr 0xffa59824
After ++ pointer's address Value of z 10 i 31 i_ptr -5924784 Address of i_ptr 0xffa59828

Pointer Initialisation

int* s_ptr = nullptr;

Pointer to integer is not same as pointer to double. C++ is strongly typed language. 

What operations can be applied on pointer?

Assignment // int *p = &i;
Dereference  // *ptr = 89;
Equality Test  // if (ptr == l_ptr)


#include <iostream>

int main()
{
   int i = 10; 
   int* i_ptr;
   double d_var;
   double* d_ptr;
   
   /* 30 is not integer pointer. */
   //i_ptr = 30;   // error: invalid conversion from 'int' to 'int*'  
     i_ptr = (int *)30;
   //i_ptr = i;   // error: invalid conversion from 'int' to 'int*'


     i_ptr = &i;
   //i_ptr = &d_var;  //error: cannot convert 'double*' to 'int*' in assignment
   //d_ptr = i_ptr;   //error: cannot convert 'int*' to 'double*' in assignment
   //&i = i_ptr;      //error: invalid lvalue in assignment 
  
   return 0;
}


The crude definition for lvalue and rvalue might be: lvalue : A value that resides in memory (heap or stack) and addressable. rvalue : A value that's not lvalue. It resides only on the right side of an assignment expression such as a literal or a temporary which is intended to be non-modifiable.

Constant with pointers

int const *ptr;
const int *ptr;

Pointer to constant int

ptr is a pointer to constant integer. Here, both refers to same. 

#include <iostream>

int main(void)
{
    int i = 10;  
    int j = 20;
    /* ptr is pointer to constant */
    const int *ptr = &i;   
  
    cout << "ptr " << *ptr << endl;;
    /* error: assignment of read-only location */   
    //*ptr = 100;
  
    ptr = &j;          /* valid */
     cout << "ptr " << *ptr << endl;;
  
    return 0;
}

Const Pointer to int

int * const ptr; 

ptr is a constant pointer to integer. 

#include <iostream>

int main(void)
{
    int i = 10;  
    int j = 20;
    /* Read-only variable */
    const int k = 30; 

    /* ptr is pointer to constant and points to an integer variable. */
    const int *ptr = &i;   
  
    /* ptr is pointer to constant and points to a constant integer variable. */
    const int *k_ptr = &k;

    /* error: invalid conversion from 'const int*' to 'int*' */
    //int *simple_ptr = &k;

    /* error: assignment of read-only location */
    //*k_ptr = 80;

    cout << "ptr " << *ptr << endl;;
    /* error: assignment of read-only location */   
    //*ptr = 100;
  
    ptr = &j;          /* valid */
    cout << "ptr " << *ptr << endl;;
  
    /******************************************/

    /* c_ptr is a constant to integer pointer. */
    int *const c_ptr = &j;
    
    *c_ptr = 60;

    /* error: assignment of read-only variable 'c_ptr' */
    //c_ptr = &k; 

    return 0;
}

 
Output:
1
2
ptr 10
ptr 20


You can also get this error "warning: address of local variable 'buffer' returned" as in the sample program.

char* BookClub::list() {
   char buffer[100];
   int buf_size = 100;
   snprintf(buffer, buf_size, "MemberName : %s MemberID : %d ", 
            members_, memberID_);
   return buffer;
}

You need to allocate a memory for this local buffer, so that it can be returned. 

char* BookClub::list() {
   char* buffer = new char[100];
   int buf_size = 100;
   snprintf(buffer, buf_size, "MemberName : %s MemberID : %d ", 
            members_, memberID_);
   return buffer;
}

Note: new is used only for pointers

Here we want to carry the value across functions to modify it, so that data should be stored in memory. 
  • Use references where ever you can and use pointers if only necessary. 
  • Don't initialise an object with new like Java. new will create a memory in heap in C++.


Comments