Activity 12-3 - Destructors and copy constructors



Destructors
We have seen that a special member function, the constructor, is called automatically when an object is first created.  On the contrary, when an object goes out of scope or is destroyed, a special member function called the destructor is called automatically. A destructor has the same name as the constructor (which is the same as the class name ), but it is preceeded by a tilde (~).  Here is an example:

class Test
{
   private:
             int *data;
   public:
            Test( )                    // Constructor (same name as the name of the class)
            {
                   *data = 0;
             }

            ~Test( )                  // Destructor (same name , but preceeded by a tilde (~))
             {
                    delete data;
              }

The job of a destructor is to free up the memory that is taken up by an object when we no longer need it.

Copy Constructors

We know that we can define and at the same time initialize an object to the value of another object. Let's say we have a class Area. We can say

Area a3(a2);                    // Copy initialization

or we can also say

Area a3 = a2;                  // Alternate syntax

Both styles of definition invoke a copy constructor. i.e., a constructor that copies its arguments into a new object. The default copy constructor, which is provided automatically by the compiler for every object, performs a member-by-member copy. This is similar to what the assignment operator does; the difference is that the copy constructor also creates a new object.

You've used the assignment operator (=) many times, probably without thinking too much about it. we've used it to initialize integers like

int a = 67;

to initialize a variable to another variable already defined and assigned as in

int b = a;

we have also used it to create objects and initialize them to the value of other objects as

Area a3 = a2;
Area a3(a2);

The assignment operator can be overloaded. Consider

class StringVar
{
   public:
            void operator =(const StringVar& right_side);
            // Overloads the assignment operator = to copy a string
            // from one object to another.
             <the rest of the definition of the class is the same as Display 12.7 in your text>
}

void StringVar::operator =(const StringVar& right_side)
{
    int new_length = strlen(right_side.value);
    if (new_length > max_length)
    {
         delete [] value;
         max_length = new_length;
         value = new char[max_length + 1];
     }
    for (int i = 0; i < new_length; i++ )
         value[i] = right_side.value[i];
   value[new_length]='\0';
}

The assignment operator can now be used just as you always use the assignment operator. string1 = string2. Notice that the argument to operator =() is passed by reference. It is not necessary to do this, buts is often a good idea.Arguments passed by value generate a copy of itself in the function to which it is passed. The argument passed to the operator =( ) function is no exception. If such objects are large, a lot of memory can be wasted. Values passed by reference don't generate copies, thus help conserve memory.

The copy constructor, the assignment operator (=) and the destructor are called the big three because if you need to define any of them , then you need to define all three. For any class that uses pointers and the new operator, it is safest to define your own copy constructor, overloaded =, and destructor.

Exercise 12.3
Write a C++ program to swap the value of two objects using pointers.  To test it, use a class that has two variable members: 1) the dynamic length of a string, int length, and 2) a pointer to the characters of a string object, char *Chars;.