#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.#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
Unique Pointer or unique_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
#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
Pointer Arithmetic :-
#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; }
- 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.
- NA
Comments
Post a Comment