...
Panel | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
Imagine you have a "House" object. This house object contains a number of "Room" objects. Now, if you want to create an exact copy of this house, you'd also want to create copies of each of these rooms. If you do a shallow copy (the default copy behavior in C++), you end up with a new house, but the rooms in this new house are exactly the same rooms as the original house. If you make a change in any of the rooms, it will reflect in both the houses because they both refer to the same set of rooms. Now, think of a deep copy. When you make a deep copy of the house, not only do you create a new house, but you also create new, separate rooms for this house. Now, if you change anything in the rooms of the new house, it will not affect the rooms in the original house. They are independent of each other. In terms of programming and specifically in C++, when you're making a deep copy, you need to define a custom copy constructor. In this copy constructor, you would allocate new memory for the pointer in the new object (the new house in our analogy) and then copy the actual values (rooms) from the source object to the newly allocated memory. By doing so, any changes you make to the objects (rooms) in the copied object (new house) do not affect the objects (rooms) in the original object (old house), preventing any unintentional changes or deletions. This is why it's known as a deep copy - you're copying everything, not just the top-level structure. |
Here is an example of a deep copy:
Code Block | ||
---|---|---|
| ||
#include <iostream>
#include <string>
using namespace std;
class Person {
public:
// 2 argument constructor
Person(const string& name, int age);
// Copy constructor
Person(const Person& other);
//Destructor
~Person();
// Functions
void introduce();
void setID(int newID); // Setter for id
private:
string name;
int age;
// Pointer to dynamically allocated memory
// it creates a new dynamic memory allocation (heap)
// and copies the value from the original Person.
int* id;
};
Person::Person(const string& name, int age) {
this->name = name;
this->age = age;
// Allocate memory for id and dynamically allocates memory
// for id and initializes it with 12345.
this->id = new int(12345);
}
Person::Person(const Person& other) {
this->name = other.name;
this->age = other.age;
// Allocate - creates a new dynamic memory allocation (heap)
// and copies the value from the original Person.
this->id = new int(*other.id);
}
Person::~Person() {
delete id; // Deallocate memory for id
}
void Person::introduce() {
cout << "Hi, my name is " << name << " and I am " << age << " years old. My ID is " << *id << "." << endl;
}
void Person::setID(int newID) {
// Set the value of id
*id = newID;
}
int main() {
Person personOne("Kevin", 39);
// Use copy constructor to create new object personTwo
Person personTwo = personOne;
personOne.introduce();
personTwo.introduce();
cout << endl;
cout << "Now lets change the ID of personTwo (pointer)" << endl;
// Change ID of personOne using the setter
personOne.setID(54321);
personOne.introduce();
personTwo.introduce();
return 0;
}
|
...
This C++ code defines a Person
class with attributes for name
, age
, and id
.
name
andage
are straightforward - astring
for the name and anint
for the age.id
is a pointer to an integer, which is dynamically allocated on the heap.
The Person
class defines the following:
A constructor
Person::Person(const string& name, int age)
: This initializes aPerson
object with aname
andage
, and dynamically allocates memory forid
and initializes it with 12345.A copy constructor
Person::Person(const Person& other)
: This is invoked when an existingPerson
object is copied. It initializes a newPerson
object with the samename
andage
as the original. Forid
, it creates a new dynamic memory allocation (heap) and copies the value from the originalPerson
.A destructor
Person::~Person()
: This is invoked when aPerson
object is destroyed (goes out of scope or is deleted). It deallocates the dynamic memory assigned toid
to prevent memory leaks.A
introduce
functionvoid Person::introduce()
: This prints thename
,age
, andid
of thePerson
.A setter function
void Person::setID(int newID)
: This sets the value ofid
for thePerson
.
In the main()
function:
Person personOne("Kevin", 39)
creates aPerson
object namedpersonOne
.Person personTwo = personOne
uses the copy constructor to create a newPerson
objectpersonTwo
that's a copy ofpersonOne
.Then, it prints the information of
personOne
andpersonTwo
, showing that both have the samename
,age
, andid
.It changes the
id
ofpersonOne
and prints the information again. You'll see thatpersonOne
'sid
has changed, butpersonTwo
'sid
remains the same, demonstrating that the copy constructor made a separate copy of theid
. This concept is often referred to as deep copying in C++.