The Big 3
Copy control is a very important concept in C++ because it
involves the creation and deletion of objects (after
all, this course is called Object Oriented Programming).
You have dealt with constructors in Python but maybe it
was not explicitly stated; every time you make an __init__ method
for your objects/class in Python, you have made
a constructor for the object/class.
When you assign a class's name followed by parenthesis to a variable
in Python (for example if you have a class called
BinarySearchTree
and you write myObject = BinarySearchTree())
you have called the class's constructor.
However, in C++, we take the creation of objects one step further;
we are now concerned about allocating and deallocating memory
because we directly tell the compiler through our code when and
how to allocate memory.
We did not have to worry about the deallocation of memory in Python
because Python automatically calls its
garbage collector when needed.
In C++ we often associate three language features
with copy control:
destructors,
copy constructors,
and assignment
operators.
We will call these the Big 3
because often times
when you need to write any one of
them, you most likely will need to write the other two.
Here are the topics we will cover in this unit:
-
Destructors
The purpose of the destructor is to destory items
that are allocated onto the heap. The syntax follows that
of the constructor except in the function
name it starts with a tilde
followed by the class name. You never call the destructors
yourself; instead the compiler calls it when the object is
not needed, when you go out of scope, or in other words,
when everything in the callstack is done.
-
Copy Constructor
The purpose of the copy constructor does
what its name is; it
creates a new object based on an existing object.
The syntax for this
is the syntax for the constructor except an
object of the same type
is passed in usually by constant reference.
To "copy" the object,
you first allocate memory for the data members.
Then you initialize
those data members to be the same as the
data members of the referenced
object.
Taken from
Sterling's notes
the Copy Constructor is called in 3 instances:
1)
SomeClass a;
SomeClass b(a);
2)
SomeClass a;
SomeClass b = a;
3)
void someFunc(SomeClass passedByValue) {}
4)
SomeClass anotherFunc ()
{ SomeClass returnedByValue; return returnedByValue; }
In the first two lines, the copy constructor is called
because you create a new object from an existing object with a
matching type.
In the third line, the copy constructor is called because
you pass an object by value which creates a copy of that
object.
In the fourth line, the copy constructor
is called because your return
by value (so you make a new object
that is a copy of that specific value / object)
-
Assignment Operator
The purpose of the assignment operator is to
set an existing object to be the
same as another existing object of the same type.
It should first remove or delete the items
stored in the object's data members,
allocate memory for the new
items, then copy the other object's data
members to the current object.
You should also check for self-assignment
(assiging an object to itself)
and at the end of the function, return the object.
The assignment operator is called when you set
an existing object equal to an existing object of
the same type.
For example:
SomeClass a;
SomeClass b;
a = b;
You might be wondering, why should the assignment operator have
a return type? Well, it should have a return type because
sometimes you want to chain assignment operators. For example:
SomeClass a;
SomeClass b;
SomeClass c;
a = b = c;
Had we not made it return a type (or in other words
we made the return type void), the last
line will not compile.
However, do note that we will have to take additional steps
in regards to copy control with inheritance,
which will be discussed when we reach the topic of inheritance.
Code
The file my_vec.cpp implements the
big 3 for our own vector class.