Skip to main content

Pointers.

I have already introduced pointers in the C++ Derived Data Types post, But, here I will be showing some practical examples and at the end of this slide, you will be understanding pointers like they are, obvious to you.
So, let' start by reminding you the basic syntax :- <data type> *<name_of_pointer>;
Below is the simple program for pointer declaration and initialization.

#include<iostream>
using namespace std;
int main(){
    int a = 20;
    
    
    int *b;     // Declaration of pointer b
    b = &a;     // Initialization of pointer b (& is used to extract the address of a)


    int *c = b; // Initialization of pointer c to pointer b

    cout << a << endl << b << endl << c << endl;
}

Okay, after reminding the basic syntax of pointers, you have to memorize the reason why we generally use pointers, I have already discussed that also, but, let me briefly describe it.

One of the memory section in our Computer memory named Heap Memory is not usable directly by our computer and we require to use the pointers to store our data to this memory for using it, But When we use it, We allocate some memory in Heap, which has to be freed when that memory has served its part.

Allocating Memory on heap is easy task in C++, and to do so we use new Operator. But, one more thing to see is that whenever you create a pointer, pointer is always present in the stack memory (What?;🤦‍♀️), I mean to say pointer itself present inside the stack memory while the data inside pointer i.e. the memory address is the address of some memory in the heap memory. To clear yourself see the below diagram.

Hope this simple pictorial representation could clear your doubt if you have any.
(NOTE- Here object could be anything like array, character, user defined class etc). 

One of the most significant use of pointer is that, You can even allocate memory for some object at runtime (read previous posts, if you haven't).
Below Program shows, how to create 1D array and 2D array of desired size using pointers.
#include<iostream>
using namespace std;

int main(){

    int si;
    cout << "Enter size of OneD array : "; cin >> si;
    int *OneD;
    OneD = new int[si];     // syntax for creating array of size "si"

    int row, col;
    cout << "Enter row and col for TwoD array"; cin >> row >> col;
    int **TwoD;

    TwoD = new int*[row];        //   -|
    for(int i = 0; i< row; i++) //     |    Syntax for creating row*col matrix/ 2darray.  
        TwoD[i] = new int[col]; //    -|


    return 0;
}

Now let me explain, what is **TwoD;?

Actually it is a pointer to pointer, let's see it through again a simple diagram.

From, this simple diagram the picture of declaring dynamic arrays where only pointer reside in the stack while row and column all are present inside the heap should be clear.

NOTE - Point to be noted here is that in the line TwoD = new int*[row]; , I wrote int*[row] not int[row], the reason is that, I need 1D array of pointers, while each pointer in this array in return points array of col.

As we have cleared the picture of pointers let's discuss, why pointer is sometimes very dangerous to use, Yes, You guessed right, The main problem of memory leak and undefined pointer(NULL pointer), could make our program to crash at first place. 

Now, you must be thinking if pointer are such dangerous, if not handled properly, why not C++ provide some built-in method to avoid de-allocation issue of pointers, but unlike Languages like Java, Python, C# etc where we are provided the built-in garbage collector, which deallocates memory automatically when not required, C++ also provide us some useful tools which are often called Smart Pointers.

But first see the following program.

#include<iostream>
using namespace std;
void fun(){
    int *p = new int[1000];
}
int main(){

    while(true){
        fun();
    }
    return 0;
}

Do, you see, what's wrong here? If not follow me.

In main() I have a loop which is always true, and in the loop, I am calling fun().

Now, let's see what is happening in fun(), here I am declaring p which is a pointer to integer and it is allocating array of 1000 integers. Now, you must be thinking there is nothing wrong here. But see clearly the loop will be going infinitely and the Heap Memory will be always be getting allocated for 1000 integers (for my compiler it's approx 4 KB), although the scope of pointer p is only in function fun() i.e. after each call the pointer p will always get deleted, but remember that memory that we allocated will not be get freed and after a certain time of execution of the above program, the program will throw an instance of bad_alloc() exception which means there is no memory left in Heap to allocate, It's scary AF;☹.

Smart Pointer is something that we could use to let the Compiler know that it should automatically handle this thing, So, that we don't require to de-allocate every time.

Let's discuss all types of Smart Pointers.

  • unique_ptr
  • shared_ptr
  • weak_ptr
  • auto_ptr
As you can see I have written 4 types here, but that auto_ptr was the older one or you can say the prototype version of unique_ptr, it means unique_ptr is the upgraded version of auto_ptr, so we don't require to discuss auto_ptr here.

Unique Pointer or unique_ptr.

The name itself describe the article itself, the word unique is meant the one pointer for one object, or if you have done math, it is one to one relation.
Using the same program given above by replacing simple pointer with unqiue_ptr.

#include<iostream>
#include<memory>
using namespace std;
void fun(){
    unique_ptr<int> p(new int[1000]);
}
int main(){

    while(true){
        fun();
    }
    return 0;
}

Now, it's the program with same functionality, but now try to execute this one, you will not get any exception of bad_alloc(), because memory is getting deallocated automatically, 

NOTE- In line unique_ptr<int> p(new int[1000]); I didn't used assignment operator because it is a parameterized constructor (We shall look at this in Classes concept in future), and also see clearly I wrote p not *p, because the definition of unique_ptr automatically makes it a pointer. 

But remember that in unique pointer only one pointer can point to an object, and if you want another pointer to point you have to use std::move() utility for doing so. See the program below.

#include<iostream>
#include<memory>
using namespace std;
int main(){

   unique_ptr<int> p1(new int(10000)); 
   
   // Now I want a another pointer that should 
   // point to same data where p1 is pointing

   unique_ptr<int> p2=p1;      // Wrong because two pointer can't point on same object

   unique_ptr<int> p3(move(p1));    // Right because it first deletes p1 and then assign
                                    // value to p3

    return 0;
}

Shared and weak pointer doesn't require that much explanation, so, I will be just giving a brief explanation.

Shared Pointer or shared_ptr

Shared pointer is little different than unique_ptr, the difference is obvious by reading their names, as unique pointer can only points to one object, shared pointer on other hand give us flexibility to use any number of pointers to point on one object, like Many to One relationship.
You can take same example given above, but remember the move utility is not used with shared pointers.
You can get the counting of pointers pointing to same object. See below program:-

#include<iostream>
#include<memory>
using namespace std;
int main(){

   shared_ptr<int> p1(new int(10000)); 
   
   // Now I want a another pointer that should 
   // point to same data where p1 is pointing

   shared_ptr<int> p2=p1;
   shared_ptr<int> p3=p1;

   cout << p1.use_count() << endl;  // To see how many pointing to same object

   return 0;

}

One thing I want you to notice is that if you have read my previous articles I have said that pointers uses arrow(->) operator to access the member functions but, as you can see clearly, I used dot(.) operator while writing p1.use_count(), even if I have previously said that p1 is a pointer. To understand this, you can think like, if you declare a smart pointer pointing to some object, you need to use arrow operator to access member functions of that object, but to access member function of smart pointer class itself, you don't require (->) operator, i.e. you could simply use dot(.) operator.

Weak Pointer or weak_ptr

It is similar to shared pointer i.e. you can have more than one pointer to same object, but it doesn't count how many of them are there, unlike in shared pointer, where we can get number of pointer to same object using .use_count() method.

Pointer Arithmetic :-

Now, let's take a brief look at pointer arithmetic, I will not discuss it as a whole concept, because, I wanted to combine with the concept of Iterators in c++, which we shall look in future.
I am taking a very big assumption that the person reading this blog is familiar with basic arithmetic operations 😂, but let's see what is different in pointer arithmetic (nothing different in my senses). Just look at the below program and everything will be clear to you.

#include<iostream>
using namespace std;
int main(){

    int arr[] = {1,2,3,4,5,6,7,8,9,0}; 

    /*
    I will try to output every element of the 
    array with the help of pointer arithmetic
    and not using loop
    */

    int *second = (arr + 1);

    cout << "first element " << *arr << endl;
    cout << "second element " << *(second) << endl;
    cout << "third element " << *(++second) << endl;
    cout << "fourth element " << *(++second) << endl;
    cout << "fifth element " << *(++second) << endl;
    cout << "sixth element " << *(++second) << endl;
    cout << "seventh element " << *(++second) << endl;
    cout << "eight element " << *(++second) << endl;
    cout << "ninth element " << *(++second) << endl;
    cout << "tenth element " << *(++second) << endl;
    cout << "Eleventh element " << *(++second) << endl;     // Wrong as there are only 10 elements
                                                            // So, we get garbage value 
                                                            // printed out, because the pointer
                                                            // is pointing to some memory address which is not
                                                            // initialized with some useful data

    return 0;    
}

If you didn't get the above program it's okay, for the first time.
So, let's break it down as always we do. All the below points are very important
  • So, let's start by reminding the phrase I previously talked about, i.e. the identifier of an array is actually a pointer.
  • Dereference Operator (*)- I have introduced this operator in operators section of this blog, and also you are seeing this continuously, throughout this section. Suppose you have pointer and you wrote a line like this cout << yourpointer << endl; , What do you think it will print, the data inside the pointer(i.e. some memory address) or the data at that memory address. Yes, it prints data inside pointer, but to print the data at the memory address, you have to use dereference operator i.e. cout << *(yourpointer) << endl;  (asterik symbol) as a unary operator.
  • I have used an extra pointer "second" which is initialized to the address of the second element of the array.
  • The pointer is changing it's data by pointing to the address of the next element, each time I used ++second.
  • At last I made my pointer to reach a pointer where it is pointing to some address which is out of the scope of our array.
(Try to read pointer arithmetic again, if you didn't get it, and if it is still confusing ask your doubts in the comments).

I will also explain function pointer when we will be covering advance topics in C++, until then keep reading.

Stay tuned for the upcoming content. For any query leave a comment below.

References.
  • NA

Comments

Popular posts from this blog

Introduction to Computer Science.

 Before directly jumping deeply in c++, let's first start by creating the roots of computer science. In this post we will answer the following question. What is Computer and How it works? What is Program and Operating system? Low Level vs High Level Language? Compiler v/s Interpreter? By Knowing All these basic concepts You will be able to understand the upcoming more complex concepts easily. Let's start answering the above questions. What is Computer and How it works? What is computer? If I answer briefly,  what is computer?  then it is just a calculator used for doing simple calculations. If I have to answer where is computer used?, then I could probably say everywhere. We are surrounded by computer, for example mobile, smartwatches, and personal computer (obviously).  The below image is the first mechanical computer that we used for calculation.                                        Abacus How computer works? The computer's internal functionality is a whole separate bra

C-style strings vs String Class.

Here, we are going to learn about, what are C-Style Strings and what is String class . So, let's start by giving you the introduction. C-Style String is nothing but, an array of characters, and from the term array we can surely assume that these are static in size i.e. the size of these C-Style strings cannot be increased or decreased. String Class is a Built-in class that provide us much more functionality than C-Style String. C-STYLE STRINGS Before learning the String class, which is full-fledged feature of C++, we should rather start by taking a look at some important things about C-Style String. C-Style Strings are actually array of characters that are terminated by a null character "\0". If you are confused with, why null character? The reason is that, It helps us to define, upto which index we have some useful data present in our character array, and after null character there may or may not be some garbage values of characters. Let's first start by showing a

Algorithms, Pseduocodes and FlowCharts.

Some Basic Knowledge. C++ is a general purpose programming language, created by Bjarne Stroustrup and was firstly released in  1985. It is an extension to C language, Reason for that is if you are familiar with C language than you must be familiar with the fact that there are no classes, templates etc. present in C language. Due to which when classes are added to C language it is named as "C with Classes", but C++ is considered as default name now.  Extra thing to remember - In "C++" the symbol "++" after C is post increment symbol and therefore, "C++" means that In C additional features are added. Now, let's define, what are algorithms? Algorithms are nothing but set of rules that must be followed to accomplish some task. (Now, What that mean?😕) let's take an example of swapping two numbers, i.e. if a = 10 and b = 20 after swapping a = 20 and b = 10. How will you write the procedure for this?  (There are many such algorithms). Accordin