You are on page 1of 10

Chapter 6

Destructors
Storage Classes

6-1

Destructors
The purpose of a constructor was to perform initial processes such as initializing
variables, opening files etc. Just as there are things that need to take place when an
object is instantiated, there are often things we need to take care of when an object ceases
to exist. A destructor is a special member function of a class that is used for resource
deallocation. The name of the destructor for a class is the class name preceded by a tilde
(~). A class' destructor is called when an object is destroyed - for automatic variables,
variables created when their block is entered and destroyed when the block is exited, this
would be when program execution leaves the scope in which an object was instantiated.
The destructor is run automatically at this time. Objects that were dynamically allocated
are not automatically destroyed when they go out of scope. These objects are destroyed
only by using the _____________________________________ on the pointer. If this is
not done, a ______________________________ will result. To further compound the
situation, any resources inside the object will also remain unreleased. Simply put, the
destructor is not run when a __________________________________________ 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 that object) goes
out of scope. Explicit destructors are required only when there are resources to be
relinquished. Destructors are not limited to giving back resources, they can perform any
task the class designer wishes them to perform when an object is destroyed.
- A destructor receives no parameters and returns no value.
- A class may have only one destructor - destructor overloading is not allowed
- Fully implemented destructors are appropriate for classes whose objects contain
dynamically allocated memory.
- Every class should contain a destructor even if the destructor does nothing.
- Unlike constructors, even if you include a destructor in your class, the compiler
will still supply and run its own synthesized destructor. It destroys each
nonstatic member in the reverse order from which it was declared. Example:
class Employee
{
public:
Employee( );
~Employee( );
private:
string empName;
};
Employee::~Employee( )
{
}

Even though the Employee destructor does nothing, the synthesized destructor will
run and call the destructor supplied by the string class to destroy empName. The
synthesized destructor does nothing to built in types.

6-2

Destructors and Inheritance


A derived class destructor is responsible only for cleaning up its own members. It does
not handle members of the base class. The compiler always implicitly invokes the
destructor for the base class. This is done in the opposite order from which they were
constructed. The derived class destructor is run first, then the base class destructors.
Recall, base class pointers have two types, a static type and a dynamic type. A base class
pointer might be referencing a derived class object. If we delete this pointer, the base
class destructor is run and the derived class members are left in an undefined state. To
make sure that the proper destructors are executed it is important to make the destructor
virtual in the base class. In this way, the destructor that is executed will depend upon
the type of the object that the pointer is pointing to rather than the type of the pointer
itself. It is a good idea to declare a virtual destructor in the base class even if that
destructor does nothing.
What about virtual constructors? Virtual constructors are not allowed as constructors are
run before an object is fully constructed thus the object's dynamic type is not complete.
Constructors and destructors are called automatically as an object comes in and out of
scope. The order in which they are called depends upon the order in which execution
enters and leaves the scope in which the objects are instantiated (this order is impacted by
the storage class of the object).

Storage Classes
An identifier's storage class determines the period of time in which an identifier exists in
memory. Some identifiers exist for a short period of time, some are created and
destroyed repeatedly, and others exist during the entire execution of the program. An
identifiers scope is where the identifier can be referenced in a program. Some exist
throughout the program while others can be referenced from only limited portions of the
program. The storage class identifiers can be split into two storage classes: automatic
storage class and static storage class. Note: Using multiple storage class identifiers in a
declaration produces a compiler error.

6-3

Automatic Storage Class


Only variables can be of automatic storage class. These variables are created when the
block in which they are declared is entered, they exist while the block is active, and they
are destroyed when the block is exited. The keywords auto and register are used
to declare variables of the automatic storage class. The parameters and local variables for
a function are normally automatic variables. Automatic storage
- is a means of conserving memory
- is an example of the principle of least privilege (why have variables in memory and
accessible when they are not needed)

auto - Used to explicitly declare variables of automatic storage class.


auto float num1, num2;
The above declaration indicates that the float variables num1 and num2
exist only in the body of the function in which the definition appears. Local
variables are by default of automatic storage class so the keyword auto is
rarely used.

register - Used to suggest to the compiler that it maintain the variable in one of the
computer's high-speed hardware registers rather than in memory. If variables
that are used extensively in a program such as counters and totals can be
maintained in hardware registers rather than in memory, this cuts down on
the overhead of repeatedly loading the variables from memory into the
registers and then storing the results back into memory. As there are only
a certain number of hardware registers available, the compiler might choose
to ignore your suggestion. Note also that many compilers today are very
good at optimizing code and can decide which variables would be better
stored in a register.
register int count = 1;
The keyword register may be used with local variables and function
parameters only.

6-4

Static Storage Class


Variables of static storage class exist from the point at which the program begins
execution. Storage for variables is allocated and initialized once when the program
begins execution and the names of functions exist from the time the program begins
execution. Even though the variables and function names exist from the start of
execution, this does not mean that these identifiers can be used throughout the program.
Storage class and the scope of an identifier are not necessarily the same.

extern - Global variables and function names by default are storage class extern.
When a variable declaration is placed outside of any block in the program,
this variable becomes global and their values exist throughout the entire
program execution cycle. These variables can be referenced by any
function that follows their declaration Likewise for function declarations.

static -

When local variables are declared with the keyword static, their values are
retained even when the function has ceased execution. These variables are
still accessible only within the block in which they were defined but their
old value is available the next time the function is called. Any numeric
variable of static storage class is initialized to zero if it is not done explicitly
by the programmer.
static int count = 1;

Calling of Constructors & Destructors


Constructors and destructors are called automatically as an object comes in and out of
scope. The order in which they are called depends upon the order in which execution
enters and leaves the scope in which the objects are instantiated (this order is impacted by
the storage class of the object). In general, destructors are called in the reverse order of
the constructor calls.
- Constructors are called for objects defined in global scope before any other function in
that file begins execution. The corresponding destructors are called when the main
function terminates or the exit function is called. Destructors are NOT called if the
program terminates with a call to the abort function. We will discuss these two functions
when we discuss exceptions.
- Constructors for automatic local objects are called when execution reaches the point
where the objects are defined and the corresponding destructors are called when the
object leaves the block in which it was defined (scope). The constructors and destructors
are called each time the object enters and exits scope. If the use of an object is
terminated with an exit or abort function call, the destructors are not invoked.
- Constructors for static local objects are called only one time when execution first
reaches the block where they are defined. The destructors are called when the main
function terminates or the exit function is called but not the abort function.
6-5

class C
{
public:
C();
~C();
};
class A
{
public:
A();
~A();
private:
C aVar;
};
class B : public A
{
public:
B();
~B();
private:
C bVar;
};
void someFunc();
int main()
{
someFunc();
B bVal;
return 0;
}
void someFunc()
{
static C funcVal;
}
C::C(){ cout << "create C\n"; }
C::~C(){ cout << "destruct C\n"; }
A::A(){ cout << "create A\n"; }
A::~A(){ cout << "destruct A\n"; }
B::B(){ cout << "create B\n"; }
B::~B(){ cout << "destruct B\n"; }

Show the output from this program.

6-6

class CreateAndDestroy
{
public:
CreateAndDestroy(int val);
~CreateAndDestroy();
private:
int privateVal;
};
void Create(void);
CreateAndDestroy first(1);
int main()
{
cout << "\t(global object before main)\n";
CreateAndDestroy second(2);
cout << "\t(local automatic in main)\n";
static CreateAndDestroy third(3);
cout << "\t(local automatic in main)\n";
Create();
CreateAndDestroy fourth(4);
cout << "\t(local automtic in main)\n";
return 0;
}
CreateAndDestroy::CreateAndDestroy(int val)
{
privateVal = val;
cout << "Construct object " << privateVal;
}
CreateAndDestroy::~CreateAndDestroy()
{
cout << "Destruct object " << privateVal << endl;
}
void Create(void)
{
CreateAndDestroy fifth(5);
cout << "\t(local automatic in create)\n";
static CreateAndDestroy sixth(6);
cout << "\t(local static in create)\n";
CreateAndDestroy seventh(7);
cout << "\t(local automatic in create)\n";
}
Show the output from this program.

6-7

Destructor Exercise
struct StringRec
{
char theCh;
StringRec* nextCh;
};
typedef StringRec* StrPtr;
class String
{
public:
String();
~String();
void SetString();
void OutputString();
int GetLength()const;
protected:
StrPtr head;
int strLength;
};
class StringModifier : public String
{
public:
StringModifier();
~StringModifier();
//Assumes the head of the string is not null and the string contains at least n characters
void InsertAfter(StringModifier& subStr, int n);
};
Implement the following functions:
String::String()
{
}
// destructor deletes the list elements and releases the memory
String::~String()
{

6-8

// read from buffer one character at a time and build the list
void String::SetString()
{
StrPtr p,last;
char tempCh;
last = head;
cout << "Enter a string: ";
cin.get(tempCh);
while(tempCh != '\n')
{

}
}
//Assumes the head of the string is not null and the string contains at least n characters
void StringModifier::InsertAfter(StringModifier& subStr, int n)
{
StrPtr p,q,r;

6-9

Name _____________________________________________
Due Date __________________
String Function Homework
Use the code from the string function exercise done in class. Using the class String and the class
StringModifier, add a member function to StringModifier called FindSubString.
The FindSubString function returns an integer representing the position of the start of the
requested sub-string, or -1 if the sub-string is not found. The first character is located at position
0. The search for the sub-string begins at "index" n.
Example 1
"Mother is at her best in her home."
Find sub-string "her" starting at position 0.
Found starting at position 3
Found starting at position 13
Found starting at position 25
There are 3 occurrences of "her" in the string.
Example 2
"Help me!"
Find sub-string "elp" starting at position 2.
No occurrences were found.

6-10

You might also like