0% found this document useful (0 votes)
30 views16 pages

Lecture 11 Copy Constructor Spring 2025

The lecture discusses copy constructors in C++, explaining their purpose and how they work. It covers both default and user-defined copy constructors, highlighting the difference between shallow and deep copies, particularly when dealing with dynamic memory. Examples are provided to illustrate the creation and initialization of objects using copy constructors, as well as the potential pitfalls of shallow copies when pointers are involved.

Uploaded by

lucifer55077
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views16 pages

Lecture 11 Copy Constructor Spring 2025

The lecture discusses copy constructors in C++, explaining their purpose and how they work. It covers both default and user-defined copy constructors, highlighting the difference between shallow and deep copies, particularly when dealing with dynamic memory. Examples are provided to illustrate the creation and initialization of objects using copy constructors, as well as the potential pitfalls of shallow copies when pointers are involved.

Uploaded by

lucifer55077
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Lecture 11

copy constructor
Today’s Lecture Contents
▪ Copy constructor
Constructors and Copy Constructors
• All class definitions include a default constructor.
• The default constructor does not take any arguments.
• It is used to initialize object data fields when no other arguments are specified.
• Besides a default constructor, a class definition also provides a default copy
constructor
• A copy constructor is a special constructor that is called whenever a new object
is created and initialized with another object's data.
• For example:
Rectangle r1(1,18); //object r1 with length and width members;
Ractangle r2(r1);
• The above statement creates object r2 and initializes it with the r1’s data.
• It uses the default copy constructor provided by the compiler to make a duplicate
copy (r2) of the already existing object (r1).
class Rectangle {
Example: Default copy
public:
constructor
Rectangle(int w=5,int l=10) {
width=w; length=l;}
Void printDimensions() {
Cout<<“Rectangle Width= “<<width<<“ length= “<<length<<endl; }
private:
int width;
int length;
};
int main() {
Rectangle r1(10,40);
Rectangle r2(r1); //creates and initializes r2 by calling default
copy constructor
r1.printDimensions();
r2.printDimensions();
}
Non-default Copy Constructor
• Like a normal constructor it is also possible to explicitly provide a copy constructor.
• In the presence of the user-provided copy constructor, the default copy constructor
will not be called.
• Most of the time, the default copy constructor is sufficient, but there will be situations
where we will need an explicit copy constructor.

• Signature of the copy constructor may look something like this:


Rectangle::Rectangle(const Rectangle &obj);
• And its full implementation may look something like this:
Rectangle::Rectangle(const Rectangle &obj) {
width = obj.width;
length = obj.length;
}
class Rectangle {
public:
Example: non-Default
Rectangle(int w=5,int l=10) { copy constructor
width=w; length=l;}
Rectangle(const Rectangle &obj) {
width = obj.width; length = obj.length;
cout<<“Rectangle created using non-default copy constructor: “;}
Void printDimensions() {
Cout<<“Rectangle Width= “<<width<<“ length= “<<length<<endl; }
private:
int width;
int length;
};
int main() {
Rectangle r1(10,40);
Rectangle r2(r1); //creates and initializes r2 by calling copy
constructor
r1.printDimensions();
r2.printDimensions();
}
when is copy constructor called?
• When is a copy of an object made?
– Passing object by value as a parameter.
void displayRectangle(Rectangle R);

– returning an object from a function by value.


Rectangle createRectangle();

– Constructing one object based on another of the same class.


Rectangle r1;
Rectangle r2(r1);
Shallow copy
• The default copy constructor simply copies the bytes of the object.
– This is called a shallow copy.
• As long as all of your object's data is inside the object, a shallow copy is
fine.
– For example, we used default copy constructor to make copy of our Rectangle
class object.
• However, if an object has a pointer to dynamic storage as a data member,
not all of its data is inside the object.
• The dynamic storage is separate from the object itself, and resides on the
free store.
• A shallow copy will simply copy the pointer to this dynamic storage without
actually making a copy of the storage contents.
• The result is that you end up with two different objects pointing to the same
chunk of dynamic storage.
Example: Shallow copy
class dynamicvar {
private:
int * ptr;
public:
dynamicvar(int n) {
cout<<“in constructor: Allocating variable on the heap: “<<endl;
ptr = new int;
*ptr = n;
}
~dynamicvar(){
cout<<"In Destructor: Dynamically allocated variable is being deleted:";
delete ptr; }
};
int main() {
dynamicvar D1(5);
D1.display();
{
Dynamicvar D2(D1);//calling default copy constructor
D2.modify(10);
D1.display(); //what will it print?
}
D1.display()// //what will it print?
}
Example: Shallow copy

• Write a customized copy constructor for the class on the previous slide.

class dynamicvar {
private:
int * ptr;
public:
dynamicvar(int n) {
cout<<“in constructor: Allocating variable on the heap: “<<endl;
ptr = new int;
*ptr = n;
}
~dynamicvar(){
cout<<"In Destructor: Dynamically allocated variable is being deleted:";
delete ptr; }
};
User defined copy constructor
• The below user-defined copy constructor does deep copy, instead of a shallow copy.

class dynamicvar {
public:
dynamicvar(int n) {
cout<<“in constructor: Allocating variable on the heap: “<<endl;
ptr = new int;
*ptr = n;
}
dynamicvar(const dynamicvar & obj) {
cout<<"in copy constructor: copying object: "<<endl;
ptr = new int;
*ptr = *(obj.ptr);
}
~dynamicvar(){
cout<<"In Destructor: Dynamically allocated variable is being deleted:";
delete ptr; }
};
Shallow Copy: Another Example
• Default copy constructors work fine unless the class contains pointer data members.
• For example, If name had a dynamically allocated array of characters (i.e., one of the
data members is a pointer to a char).

#include <string.h>
class name {
public:
name(const char* name_ptr = ""); //default constructor
~name() { delete ptr; } //destructor
private:
char* ptr; //pointer to name
int length; //length of name including null char
};
name::name(const char* name_ptr) { //constructor
length = strlen(name_ptr); //get name length
ptr = new char[length+1]; //dynamically allocate
strcpy(ptr, name_ptr); //copy name into new space
}

int main() {
name smith(“Sue Smith”); //one argument constructor
name clone(smith);//using default copy constructor
}
Copy Constructors
• the following shallow copy is disastrous!

n a m e sm it h ("Su e Sm it h "); / / on e a r g con st r u ct or u se d


n a m e clon e (sm it h ); / / d e fa u lt cop y con st r u ct or u se d

smith clone
ptr S ptr
u
length=10 length=10
e

S
m
i
t
h
'\0'
Defining your own Copy Constructors
• To resolve the issue, we must write a copy constructor whenever dynamic
member is allocated on an object-by-object basis.→ This copy constructor
makes a "deep copy" of the object

• A copy constructor takes an instance of the same class as a constant


reference argument.

• They have the form:

name(const name & class_object);

• Notice the name of the “function” is the same name as the class, and has no
return type
• The argument’s data type is that of the class, passed as a constant
reference
Defining your own Copy Constructors
class name {

char* ptr; //pointer to name


int length; //length of name including nul char
public:
name(const char* = ""); //default constructor
name(const name &); //copy constructor
~name() { delete ptr}; //destructor
};

name::name(const char* name_ptr) { //constructor


length = strlen(name_ptr); //get name length
ptr = new char[length+1]; //dynamically allocate
strcpy(ptr, name_ptr); //copy name into new space
}

name::name(const name &obj) { //copy constructor


length = obj.length; //get length
ptr = new char[length+1]; //dynamically allocate
strcpy(ptr, obj.ptr); //copy name into new space
}
Defining your own Copy Constructors
• Now, when we use the following constructors for initialization, the two
objects no longer share memory but have their own allocated

smith clone
ptr S S ptr
u u
length=10 length=10
e e

S S
m m
i i
t t
h h
'\0' '\0'

You might also like