Section 13.3. The Destructor


13.3. The Destructor

One purpose of a constructor is to provide for the automatic acquisition of a resource. For example, a constructor might allocate a buffer or open a file. Having allocated the resource in the constructor, we need a corresponding operation that automatically deallocates or otherwise releases the resource. The destructor is a special member function that can be used to do whatever resource deallocation is needed. It serves as the complement to the constructors of the class.

When a Destructor Is Called

The destructor is called automatically whenever an object of its class is destroyed:

      // p points to default constructed object      Sales_item *p = new Sales_item;      {                                // new scope          Sales_item item(*p);  // copy constructor copies *p into item          delete p;             // destructor called on object pointed to by p      }                         // exit local scope; destructor called on item 

Variables such as item are destroyed automatically when they go out of scope. Hence, the destructor on item is run when the close curly is encountered.

An object that is dynamically allocated is destroyed only when a pointer pointing to the object is delete d. If we do not delete a pointer to a dynamically allocated object, then the destructor is never run on that object. The object will persist forever, leading to a memory leak. Moreover, any resources used inside the object will also not be released.

The destructor is not run when a reference or a pointer to an object goes out of scope. The destructor is run only when a pointer to a dynamically allocated object is deleted or when an actual object (not a reference to the object) goes out of scope.



Destructors are also run on the elements of class type in a containerwhether a library container or built-in arraywhen the container is destroyed:

      {          Sales_item *p = new Sales_item[10]; // dynamically allocated          vector<Sales_item> vec(p, p + 10);  // local object          // ...          delete [] p; // array is freed; destructor run on each element       }   // vec goes out of scope; destructor run on each element 

The elements in the container are always destroyed in reverse order: The element indexed by size() - 1 is destroyed first, followed by the one indexed by size() - 2 and so on until element [0], which is destroyed last.

When to Write an Explicit Destructor

Many classes do not require an explicit destructor. In particular, a class that has a constructor does not necessarily need to define its own destructor. Destructors are needed only if there is work for them to do. Ordinarily they are used to relinquish resources acquired in the constructor or during the lifetime of the object.

A useful rule of thumb is that if a class needs a destructor, it will also need the assignment operator and a copy constructor. This rule is often referred to as the Rule of Three, indicating that if you need a destructor, then you need all three copy-control members.



A destructor is not limited only to relinquishing resources. A destructor, in general, can perform any operation that the class designer wishes to have executed subsequent to the last use of an object of that class.

The Synthesized Destructor

Unlike the copy constructor or assignment operator, the compiler always synthesizes a destructor for us. The synthesized destructor destroys each nonstatic member in the reverse order from that in which the object was created. In consequence, it destroys the members in reverse order from which they are declared in the class. For each member that is of class type, the synthesized destructor invokes that member's destructor to destroy the object.

Destroying a member of built-in or compound type has no effect. In particular, the synthesized destructor does not delete the object pointed to by a pointer member.



How to Write a Destructor

Our Sales_item class is an example of a class that allocates no resources and so does not need its own destructor. Classes that do allocate resources usually need to define a destructor to free those resources. The destructor is a member function with the name of the class prefixed by a tilde (~). It has no return value and takes no parameters. Because it cannot specify any parameters, it cannot be overloaded. Although we can define multiple class constructors, we can provide only a single destructor to be applied to all objects of our class.

An important difference between the destructor and the copy constructor or assignment operator is that even if we write our own destructor, the synthesized destructor is still run. For example, we might write the following empty destructor for class Sales_item:

      class Sales_item {      public:         // empty; no work to do other than destroying the members,         // which happens automatically          ~Sales_item() { }         // other members as before      }; 

When objects of type Sales_item are destroyed, this destructor, which does nothing, would be run. After it completes, the synthesized destructor would also be run to destroy the members of the class. The synthesized destructor destroys the string member by calling the string destructor, which frees the memory used to hold the isbn. The units_sold and revenue members are of built-in type, so the synthesized destructor does nothing to destroy them.



C++ Primer
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2006
Pages: 223
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net