Sunday, 27 May 2018

STL is all about copying

These days, C++ programmers don't have to write their own containers like list, stack, queue, string, dictionary, set, map etc. STL provides all these containers. Hence it is a great savior. otherwise one may spent half of its time debugging these data structure if she/he encounter crash or bug. since this library is reliable you can focus on your algorithm without worrying about data structure implementation. But still you have to understand how it works and use it carefully. Here we will talk about one item that you can take care of :

STL work on copying: 

STL works on principle of copying. It copies the data when u add data to it, delete data from it, get data from it, iterate over it. 

When it is about copying of built-in data types, it does not cost much but when it comes to user defined data type, copying means calling copy constructor function.
e.g. If I want to save integers in a list and print at the end, code will look like this. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
int main() {
  std::list<int> l;
  l.push_back(1);
  l.push_back(5);
  l.push_back(10);

//! do other stuff and finally print
  auto iter = l.begin(), iter_end = l.end;
  for(; iter != iter_end ; ++iter) {
    int value = *iter;
    cout<<value<<endl;
  }
}

This code will work perfectly fine. There is no issue in it.

but now let us save info of students in list.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class student {
  int roll_num;
  char *name;
  char *address;

public :  

//! constructor
//! destructor
//! copy constructor
  student(const student &rhs) {
   roll_num = rhs.roll_num;
   name = new char[strlen(rhs.name)+1];
   strcpy(name,rhs.name);
   address = new char[strlen(rhs.address)+1];
   strcpy(address,rhs.address);

 }
};

int main() {
   student s1(1,"abcdef","address1");
   student s2(2,"dwse","address2");
   student s3(3,"rrrr","address3");
   list<student> l;
   l.push_back(s1);
   l.push_back(s2);
   l.push_back(s3);
//! do other stuff and finally print
   auto it = l.begin(), it_end = l.end();
   for(; it != it_end ; ++it) {
     student s = *it;
     cout<<s.get_name()<<endl;
     cout<<s.get_roll_number()<<endl;
   }

}

This seems same as we wrote it for list of integers. But you can make this program work faster or in other words, this program works slower. How??

Answer is because of copying.  Now you will be wondering where did copy happen? I didn't copy anywhere.

let us start dry running this code.
  • at #22,#23 and #24 constructor of student class will be called. 
  • at #25 , list will be created.
  • at #26,#27 and #28 elements i.e. s1,s2 and s3 will be put into list by copying i.e. by calling copy constructor
  • at #30 , I am setting the iterators.
  • at #32, I am getting current element from the list which is returned by copying.
  • Next lines does the printing job.
Here I am making unnecessary copies of each student object twice but without knowing. This is very simple example where you might hardly notice any time glitch but imagine if there is some bigger class that has 100s or 1000s of complex data members and your list size is also in millions.  

Now we have identified the problem, what is its solution? 
You can't change working of STL. 

Answer is save pointers in STL containers instead of direct objects. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class student {
  int roll_num;
  char *name;
  char *address;

public :  

//! constructor
//! destructor
//! copy constructor

  student(const student &rhs) {
   roll_num = rhs.roll_num;
   name = new char[strlen(rhs.name)+1];
   strcpy(name,rhs.name);
   address = new char[strlen(rhs.address)+1];
   strcpy(address,rhs.address);

 }
};

int main() {
   student *ps1 = new student(1,"abcdef","address1");
   student *ps2 = new student(2,"dwse","address2");
   student *ps3 = new student(3,"rrrr","address3");
   list<student*> l;
   l.push_back(ps1);
   l.push_back(ps2);
   l.push_back(ps3);
//! do other stuff and finally print
   auto it = l.begin(), it_end = l.end();
   for(; it != it_end ; ++it) {
     student *s = *it;
     cout<<s->get_name()<<endl;
     cout<<s->get_roll_number()<<endl;
   }

}

Here I am saving pointers in list and when element will be added or retrieved from list it will add/return you copy of pointer but not copy of object which is fine.

In nut shell, save pointers instead of object(of user defined data type) in STL containers. 

Sunday, 20 May 2018

What is operating systems and why it is needed

Operating Systems is a computer program that manages computer hardware. 

This is a very simple line but it has a very deep meaning. If you can understand this simple yet powerful line, journey to understand internal of OS would be much more easier.

OS is an intermediate layer between user and hardware of computer. Roughly, you can divide computer system in four components :
  • Hardware - CPU, Input output devices , memory etc
  • OS
  • Application Program - word, web-browser,notepad etc
  • User
Operating system controls and coordinates the use of hardware among various application resources. In itself operating system does not do anything. It just manages and coordinates various resources so that all application program can run smoothly.

Just to give you an idea of how important OS is for us, let us assume that we don't have an OS . 

We have all hardware resources and say we want to run multiple programs on it. We want to listen to songs while writing my blog in web-browser and at the same time I also want that my email client keeps on checking for new email in background. How would you do it?  For now, forget about how all this will work in parallel. Let us assume that I want to write blog for sometime and then want to listen music for sometime and then again want to switch to my blog

We have one CPU, I will load "writing blog" program into it and run it  (for now don't go into details of How program is loaded and run). After sometime, I will load media player for playing songs and again I will load "writing blog" program into memory. 

Isn't switching from one program to another a tedious task? OS does this tedious task for you. This is just one example, OS does so many such things for you. 


Coming back to question of running multiple applications in parallel, you might be surprised that how is it possible when we have one processing Unit. It does not seem possible to run multiple Applications on one processor/Hardware. Confused?

You are right that at one point of time, CPU can run only one program. It is just illusion when you see multiple applications running on one processor and this illusion is created by OS. OS keeps on switching between different application and this switching happens so fast that it appears like parallel processing.
Could we manually do switching so fast? I don't think so.

There is much more in OS than this. I hope now you can appreciate the concept of OS.

Although there is no well defined/accepted definition of OS, OS is everything that your OS provider like Microsoft windows, Linux etc provide you. But now it is becoming important to define what constitutes Operating Systems.
Did you know? In 1998, the United States Department of  justice filed suit against Microsoft, in essence claiming that Microsoft included too much functionality in its OS that prevents competition from application vendors.


References:
sixth edition of Operating System Concepts by Silberschatz, Galvin and Gagne

Friday, 18 May 2018

const char* vs char * const

What is the difference between line 9 and line 10

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    char* str = new char[8];
    strcpy(str,"abcdefg");
    const char * str1 = str;
    char * const str2 = str;
    //str1[1] = 'c';
    //str2 = str1;
    return 0;
}

Line 9 means,   str1 is a pointer to constant character string which means that once you assigned it a string, You can't change content of the string with pointer str1.
i.e. if I uncomment line #11, it will give us  compilation error.

Line 10 means, str2 is constant pointer to character string which means that pointer is constant not string i.e. You can not make str2 to point to some another pointer.
i.e. if I uncomment line #12, it will give us compilation error.

But following lines are valid.

1
2
str1 = str2;
str2[0] = 'c';

One thumb of rule that will help you to remember is that you start reading from right to left. e.g.

If you read line #9, you should read it as str1 is pointer to character string that is constant
If you read line #10, you should read it as str2 is constant pointer which points to character.

Now isn't it easy to understand?

Now let us see what does following code mean?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int main()
{
    char* str = new char[8];
    strcpy(str,"abcdefg");
    const char * const str3 = str;
    //str3 = str2;
    //str3[3] = 'a';

    char const *str4 = str1; // equivalent to  const char *str4
    //str4[0] = 'c';
    
    char const * const str5 = str; // eqivalent to const char * const str5
    return 0;
}
Line #5 means that str3 is constant pointer that points to character string which is constant.

If I uncomment line #6 and #7 it will give us compilation error because neither you can't change content of string nor content of pointer i.e. pointer can't point to a different string.

Line #9 means that str4 is a pointer that points to constant character string. Hence str4 and str1 in first code snippet are equivalent. There are two ways to write same statement.

Similarly str5 and str3 are equivalent.

In nut shell, if you remember the thumb rule(i.e. read from right to left) You don't have to memorize anything. 

Thursday, 17 May 2018

importance of constructor and destructor in object oriented programming

what is constructor?
Constructor is a function that is called by your program when object is created and it has following properties :
  1. It has same name as that of class
  2. It has no return type (not even void)
what is destructor?
Destructor is function that is called by your program when object is destroyed and it has following properties :
  1. It has same name as that of class
  2. it has no return type

but then how would these two functions be distinguished? in destructor's name there is an extra tilde(~) symbol. 

e.g.


class Dummy {

public :

  Dummy() {
    cout<<"inside the constructor"<<endl;
  }
  ~Dummy() {
     cout<<"inside the destructor"<<endl;
  }
};

P.S. - since I am a c++ programmer, so you will see all examples in C++.

But why was it introduced, how does it ease programmer's life?

To answer these questions, let us see how to create a student struct in C when OOPs was not there (note that when I say C, it means that I am talking about code that C compiler can compile)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct student {

   int roll_number;
   char *name;
   char *address;
};

int main() {
  struct student S1,S2;

  S1.roll_number = 1;
  S1.name = (char*)malloc(7); //6 for abcdef + 1 for termination character
  strcpy(S1.name,"abcdef");
// similar code for address

  S2.roll_number = 2;
  S2.name = (char*)malloc(5);
  strcpy(S2.name,"zyxw");

//! do the other stuff like printing etc
//! now we are done with student objects.
//! let us clean them
  free(S1.name);
  free(S1.address);
  free(S2.name);
  free(S2.address);
//! name and address has to be cleared because I created them with malloc
//!  and hence it is my responsibility to free the memory.
//! for roll number, i didn't use malloc 
//! so it will be automatically deleted
//! Ahh finally I am done
}

Now let us try to do same job with some object oriented programming language like C++ that supports constructor and destructor :


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class student {
  int roll_number;
   char *name;
   char *address;

public :

  student(int rno, char *n, char *a) {
    roll_number = rno;
    name = new char[sizeof(char)*strlen(n)];
    strcpy(name,n);
    address =  new char[sizeof(char)*strlen(a)];
    strcpy(adress,a);
  }
  ~student() {
    delete [] name;
    delete [] adress;
   }
};

int main() {
  student S1(1,"abcdef","some valid address1");
  student S2(2,"zyxw","some valid address2");
  
}


When line number 22 and 23 is hit, constructor of student class is called which automatically takes care of creating data members of object.

Similarly, when object goes out of scope, which is at the end of main function here, it is automatically deleted which in turn calls its destructor and in the destructor you have already taken care of clearing memory that you allocated using malloc/new.

Isn't it very simple? You just write your constructor and destructor carefully. Rest, everything will be taken care by compiler itself.

Now one may argue that it can be achieved using some C functions similar to constructor and destructor e.g. my_constructor and my_destructor.

It can be done. infact, people work only this way if they have to write code in C but it has its disadvantages. e.g.
User still have to call these functions explicitly. For construction it may still be fine. Like in above example, function will be called at #21 and #22 but one may forget to call destuctor function which in case of C++ compiler, it is automatically called. 

what is array

Array is one of the simplest and most  sophisticated data structures. In array data is stored at contiguous memory locations. E.g. say you h...