Thursday, 3 July 2014

When are static objects destroyed?

What is static keyword in C++?

static keyword can be applied to local variables, functions, class’ data members and objects in C++. static local variable retain their values between function call and initialized only once. static function can be directly called using the scope resolution operator preceded by class name . C++ also supports static objects.

What are static objects in C++?
An object become static when static keyword is used in its declaration. See the following two statements for example in C++.
Test t;             // Stack based object
static Test t1;     // Static object 
First statement when executes creates object on stack means storage is allocated on stack. Stack based objects are also called automatic objects or local objects. static object are initialized only once and live until the program terminates. Local object is created each time its declaration is encountered in the execution of program.
static objects are allocated storage in static storage area. static object is destroyed at the termination of program. C++ supports both local static object and global static object
Following is example that shows use of local static object.
#include <iostream>
class Test
{
public:
    Test()
    {
        std::cout << "Constructor is executed\n";
    }
    ~Test()
    {
        std::cout << "Destructor is executed\n";
    }
};
void myfunc()
{
    static Test obj;
} // Object obj is still not destroyed because it is static
 
int main()
{
    std::cout << "main() starts\n";
    myfunc();    // Destructor will not be called here
    std::cout << "main() terminates\n";
    return 0;
}
Output:
main() starts
Constructor is executed
main() terminates
Destructor is executed 
If we observe the output of this program closely, we can see that the destructor for the local object named obj is not called after it’s constructor is executed because the local object is static so it has scope till the lifetime of program so it’s destructor will be called when main() terminates.

Q. What happens when we remove static in above program?
As an experiment if we remove the static keyword from the global function myfunc(), we get the output as below:
main() starts
Constructor is called
Destructor is called
main() terminates
This is because the object is now stack based object and it is destroyed when it is goes out of scope and its destructor will be called.
Q. How about global static objects?
The following program demonstrates use of global static object.
#include <iostream>
class Test
{
public:
    int a;
    Test()
    {
        a = 10;
        std::cout << "Constructor is executed\n";
    }
    ~Test()
    {
        std::cout << "Destructor is executed\n";
    }
};
static Test obj;
int main()
{
    std::cout << "main() starts\n";
    std::cout << obj.a;
    std::cout << "\nmain() terminates\n";
    return 0;
}
Output:
Constructor is executed
main() starts
10
main() terminates
Destructor is executed

Wednesday, 2 July 2014

C++ Copy Constructor

The copy constructor is a constructor which creates an object by initializing it with an object of the same class OR
A copy constructor is a special constructor for a class/struct that is used to make a copy of an existing instance. According to the C++  standard, the copy constructor for MyClass must have one of the
following signatures:
1
2
3
4
  MyClass( const MyClass& other );
  MyClass( MyClass& other );
  MyClass( volatile const MyClass& other );
  MyClass( volatile MyClass& other );
 The copy constructor is used to:
 1) Initialize one object from another of the same type.
 2) Copy an object to pass it as an argument to a function.
 3) Copy an object to return it from a function.
If a copy constructor is not defined in a class, the compiler itself defines one.If the class has pointer variables and has some dynamic memory allocations, then it is a must to have a copy constructor. The most common form of copy constructor is shown here:
classname (const classname &obj) {
   // body of constructor //
}
Here, obj is a reference to an object that is being used to initialize another object.
#include <iostream>

using namespace std;

class Line
{
   public:
      int getLength( void );
      Line( int len );             // simple constructor
      Line( const Line &obj);  // copy constructor
      ~Line();                     // destructor

   private:
      int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
   *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// Main function for the program
int main( )
{
   Line line(10);

   display(line);  // this calls copy constructor //


   return 0;
}
When the above code is compiled and executed, it produces the following result:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Let us see the same example but with a small change to create another object using existing object of the same type:
#include <iostream>

using namespace std;

class Line
{
   public:
      int getLength( void );
      Line( int len );             // simple constructor
      Line( const Line &obj);  // copy constructor
      ~Line();                     // destructor

   private:
      int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
   *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// Main function for the program
int main( )
{
   Line line1(10);

   Line line2 = line1; // This also calls copy constructor

   display(line1); // this calls copy constructor //
   display(line2); // this calls copy constructor //


   return 0;
}
When the above code is compiled and executed, it produces the following result:
Normal constructor allocating ptr
Copy constructor allocating ptr.
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!
Freeing memory!

Dangling pointer in C

Dangling Pointer in C
  1. Dangling pointers arise when an object is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.
  2. In Short Pointer Pointing to Non-Existing Memory Location is called  Dangling Pointer.
There are different ways where Pointer acts as “Dangling Pointer“.

Way 1 :Using Free / De allocating Memory
#include<stdlib.h>
{
    char *ptr = malloc(Constant_Value);
    .......
    .......
    .......
    free (ptr);      /* ptr now becomes a dangling pointer */
}
  1. Character Pointer is Declared in the first Step.
  2. After some statements we have deallocated memory which is previously allocated.
  3. As soon as “Memory is Deallocated Pointer is now Dangling“.
  4. Problem : If any pointer is pointing the memory address of any variable but after some variable has deleted from that memory location while pointer is still pointing such memory location. Such pointer is known as dangling pointer and this problem is known as dangling pointer problem.
Q . How to Ensure that Pointer is no Longer Dangling ?
#include<stdlib.h>
{
    char *ptr = malloc(Constant_Value);
    .......
    .......
    .......
    free (ptr);  /* ptr now becomes a dangling pointer */
    ptr = NULL   /* ptr is no more dangling pointer */
}
  • After Deallocating memory Initialize Pointer to NULL so that pointer is now no longer dangling .
  • Initializing Pointer Variable to NULL Value means “Now Pointer is not pointing to anywhere
Way 2 :Out of Scope
#include<stdlib.h>
void main()
 {
   char *ptr = NULL;
   .....
   .....
   {
       char ch;
       ptr = &ch;
   } 
   .....   /* dp is now a dangling pointer */
}
  1. Character Pointer is Declared in the first Step.
  2. Pointer Variable ‘ptr’ is pointing to Character Variable ‘ch’ declared in the inner block .
  3. As character variable is non-visible in Outer Block , then Pointer is Still Pointing to Same Invalid memory location in Outer block , then Pointer becomes “Dangling”

Q. How to avoid dangling pointer ? 
     use smart pointer