A copy constructor creates a clone (duplicate copy) of an existing object by initializing a new object, with an existing object of the same class.
Copies of an object are made when :
A declaration is made with initialization from another object, example,
Person p("Ahmed"); // constructor.
Person q =p; // copy constructor.
Person h ( p ); // copy constructor.
Parameters are passed by value.
An object is returned by a function.
C++ calls a copy constructor to make the copy. If there is no copy constructor defined for the class, C++ uses the default copy constructor which copies each field, ie, a shallow copy.
When copying an object of a class containing no explicit pointers ( only data ) we use the default copy constructor . All data will be copied including the arrays and strings .
All these statements are equal in this case :
(1) ClassName a,b ;
b=a;
(2) ClassName a;
ClassName b=a;
(3) ClassName a;
ClassName b(a);
See example default copy constructor with no pointers .
What if pointers exist in class ? What will happen if new object is copied from an existing object ?
See example default copy constructor with pointers.
|
(3) Overloaded copy constructor |
Will work only in the time of declaring an object and initializing it .
(1) ClassName a;
ClassName b=a;
(2) ClassName a;
ClassName b(a);
Will not work when using assignment statement .
(1) ClassName a,b ;
b=a;
See Example overloaded copy constructor with pointers
|
( 4 ) Overloading the Assignment Operator = |
The assignment operator=( ) can be overloaded
by declaring a nonstatic member function. For example,
class String {
..
String& operator = (String& str);
..
}
This code, with suitable definitions of String::operator =(), allows string
assignments str1 = str2 just like other languages.
If, for any class X, there is no
user-defined operator =, the
operator = is defined by default as a member-by-member assignment of
the members of class X:
X& X::operator = (const X& source)
{
// memberwise assignment
}
See Example Overloading the Assignment Operator =
ClassName :: ClassName ( const ClassName & object_being_copied )
The copy constructor takes a reference(&)
to a const parameter. It is const to guarantee that the copy constructor doesn't change it,
and it is a reference parameter
since a value parameter requires making a copy, which would invoke the copy
constructor, which would make a copy of its parameter, which would invoke the
copy constructor, which ...
Here is an example of a copy constructor for the Employee class.
class Employee {
public:
Employee (const Employee& e); // copy constructor
{
salary = e.salary;
grade = e.grade;
}
} .... Employee e; // calls our default constructor Employee e2 = e; // calls our copy constructor. |
Suppose you had a class called Tree and had defined a Tree object called Pine1.
To create a clone,
you could enter:
Tree Pine2(Pine1); or:
Tree Pine2 = Pine1;
If you had no copy constructor defined, then the compiler would supply a default
"copy constructor" to create the clone.
Note: The first notation "Tree
Pine2(Pine1);", is the current preferred
syntax. The second notation "Tree Pine2 = Pine1;",
is now considered obsolete. However both forms are given here because a
programmer is likely to encounter both.
Copying an object using the default copy constructor may work for simple objects. However, if there were pointers in the original object, only the pointers would be duplicated, not the data that was being pointed to.
Following the previous example,
suppose Tree objects had an integer data member, and a pointer data member to a
character string. Pine1's pointer would have the address of the same data
as Pine2's pointer! There would then be two ways of accessing (and
modifying!) the same data. This type of a copy operation is called a
shallow copy
because the "pointed-to" data is not copied when a 'clone' is made. This
is not a true clone.
If pointers are part of an object,
you need a
deep copy
Don't write copy constructor if shallow copies are ok
If the object has no pointers to dynamically allocated memory, a shallow copy is probably sufficient. Therefore the default copy constructor, default assignment operator, and default destructor are ok and you don't need to write your own.
Shallow Copy Example
PtrList ptrList list,list2_shallow_copy ;
list.insertFront(1);
list.insertBack(2);
list.insertConditional(3);
list2_shallow_copy = list;

Deep Copy Example
ptrList list3_deep_copy(list); // OR ptrList list3_deep_copy =list ;
