Copy Constructors, Assignment Operators,
Destructors
The following files are used in this lab:
- date2.h - Declaration for the Date class
- date2.cc - Definition/Implementation for Date class
- testDateCopy.cc - A example program using the copy
constructor and assignment with the Date class.
- snode.h - Declaration file for the SimNode class
- snode.cc - Definition/Implementation for the SimNode class
- olist.h - Declaration for the OrderedList class
- olist.cc - Definition for the OrderedList class
- testListCopy1.cc - Example program
illustrating problems with default copy constructor and assignment on
linked lists. Also shows when destructor is called.
- testListCopy2.cc - Another example
illustrating the hazards of no copy constructor or assignment.
C++ provides default destructors, copy constructors, and assignment operators
for objects. These work fine for classes that do not use pointers. However,
classes with pointers and dynamically allocated memory should define versions
of these to correctly allocate and deallocate memory. All three should be
provided.
Copy Constructors
C++ provides a default copy constructor that is invoked with either
of the following object declarations:
ClassName objectName(objectToCopy);
ClassName objectName = objectToCopy;
Either of these declarations sets up the object and copies each data
member of the objectToCopy to the corresponding data
member of the new object.
Warning For data members that are pointers the pointer is
copied but NOT the actual data so the two pointers are now aliases
for the same place in memory. This is called a shallow copy
and causes huge problems!
Assignment Operator
C++ provides a default assignment operator for objects that copies
each data member of the object. For example, the code
object1 = object2;
will copy each data member of object2 into the corresponding
data member of object1. As for the copy constructor, if the
data member is a pointer only the pointer is copied.
Destructors
The destructor for a class is automatically called when an object goes
out of scope. If there is no destructor provided for the class the
default destructor is called; otherwise, the one provided in the class
is called. The destructor should be responsible for freeing all memory
used by an object.
Syntax for the declaration: ~ClassName()
If the class contains a linked list the default destructor frees only the
pointer to the beginning of the list. The programmer should write
code to delete all nodes from the list.
Exercises
- Compile and run testDateCopy.cc and study the code.
No copy constructor
or assignment operator has been defined for the Date class so
the program is using the defaults provided by C++.
- Note that the code behaves as expected.
- Recall (from class) that the copy constructor
and the overloaded assignment operator have
been commented out of the OrderedList class. The destructor
code only has a message that the destructor has been called.
Leave them as is until told to change them!!!
- Now compile and run testListCopy1.cc. This is the code
we studied and traced in class. The output should be as expected.
- Study the code in testListCopy2.cc and trace it. Draw diagrams
as we did for testListCopy1 and indicate what you expect the output
to be.
- Now compile and run testListCopy2.cc.
Study the output and compare it to your trace. If it is different
do your trace again!
- Note that there is a "delete node" statement commented out
after the first node is removed from the list. Remove the comment so the
node is actually deleted (returned to the memory heap).
Run the program, and examine the output. You should notice
that the lists are different from before.
- What seems to have happened
to the node that was deleted?
- Retrace the program (using your assumption about what happened to
the deleted node). Draw the lists and pointers to
show what is now happening with the lists.
- Remove the comments that comment out the copy constructor
and the assignment operator (in both olist.h and olist.cc).
Compile and rerun both testListCopy programs.
You should now observe
correct behavior.
- Finally, the current destructor does nothing but print a message.
It should actually remove and delete each node on the list.
Similarly the assignment operator should reclaim all nodes from
the current list before reassigning the object.
So, modify the class as follows:
-
Add a function to actually delete the nodes in the list and
return them to free store.
- Update the destructor to call the function to delete the
nodes.
- Similarly add code in the assignment operator to delete
the nodes in the current list before reassigning.
Hand in (Thursday, April 14): Written answers to questions and
your traces plus a copy of
the olist.cc program that you modified.