Page excerpted from Copy Constructors topic of a second year course in Advanced Programming
Here is the declaration of a simple Array
class with a constructor, destructor and a copy constructor.
The implementation of the copy constructor mimics the implicit copy constructor provided by the compiler. The mimicry is to allow the copy constructor to be traced into by the Teaching Machine
Trace through the program using linked view. set(Array array, double value)
is an external function to set all elements in array
to value
.
Code Notes
1. Step into main
to the declaration of Array A
. Click stepOver ()once to create the
A
object. It appears, unititialized, in local memory and in the linked view and the constructor is loaded into the Expression Engine.
2. Click stepOver again to call the constructor which creates the actual space for the array in the heap and initializes it to all zeros.
3. Step into ()the
set
function, (which is not a member function).
4. Step again to initialize the first parameter, array
. The copy constructor gets called because set
passes array
by value.
5. Step through the copy constructor while it constructs a shallow copy of A
by copying only the fields in local memory. A
and array
now point at the same heap data.
6. On returning to the set
function, step one more time to create space for and initialize val
to 3.0
.
7. Step through the set
function to load the heap area with 3.0
's. The process may be hastened by putting the cursor on the line with the closing }
for set
then clicking runToCursor ( ). The heap allocation should be filled with
3.0
's
8. Click on stepInto at the closing }
. The destructor gets called to destruct the copy, array
.
9. Click through the destructor. A
's heap space gets deleted!
10. Follow a similar process for the remaining two examples on the page.
When the set
is invoked on A
, array
is a copy of A
because set
passes by value.
The copy is a shallow one so the two share the actual array data.
When set is finished the destructor is automatically called, destroying A
's data as well as array
's.
Deep Copy
Here's a copy constructor for Array that does a deep copy.
Now set
fails for the classic reason that it is being invoked on a copy.
The corrected version.
At this point a question is posed
What's the difference? Why did the "incorrect" version work before, but not now?
The incorrect version of set passes in an Array object by value. This means that a copy of the object gets made and the value gets set in that copy.
This worked in the case of a shallow copy because the copy and the original Array shared the same data in the heap.
So when that data area got set in the copy, it was set in the original as well.
Once we created a true deep copy, the data area was set in the copy but not in the original and the set data was lost once the set function was ended.
Passing the Array object to set by reference solves the problem.
Examples Shown in Full