C++ Copy Constructors
Tags: cpp, oop, computerscience
Published: 2021-03-14 06:48:19

<h2><i>Objective</i></h2>

<p>In this article, I will explain what a copy constructor is and the differences between a deep copy and a shallow copy. I will show you how you can implement both copy constructor's through code snippets and I will explain what we are doing line by line. By the end of this article, you will be able to implement your own copy constructors confidently. </p>

<h2><i>What Are Copy Constructors?</i></h2>

<p>A Copy Constructor is a special constructor that initializes an object by copying from another object.</p>

<p><b>Example One: Shallow Copy</b></p>


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zob6ou8dkmzvvl40acgi.png)

<h4> Let's break this down: </h4>

<p>Here, we created a simple class called Student. It has a private variable called <i>name</i> and <i>age</i>. We also have two functions that are public called <b>set_dimensions</b> and <b>show_data</b>. </p>

```

class Student {
private:
    int age;
    std::string name;
public:
    Student (std::string name, int age) {
        this->name = name;
        this->age = age;
   }
    void show_data() {
        std::cout << "Name:  " << name << "\n";
        std::cout << "Age: " << age << "\n";
    }

``` 


<p> In the <b>Student</b> constructor, it takes in a parameter of <b>name</b> and <b>age</b>. That parameter is pointing to the variable of <i>name</i> and <i>age</i>  in the Student class.</p>


```
Student(std::string name, int age) {
    this->name = name;
    this->age = age;
};

```

<p> In <b>show_data</b>, we are printing a statement to the console and passing <b>name</b> and <b>age</b> in. </p>

```
void show_data() {
    std::cout << "Name:  " << name << "\n";
    std::cout << "Age: " << age << "\n";
}
```

<p> Now, let's move on to the main function. Here, we are instantiating an object called <b>s1</b></p>

```
int main() {
    Student* s1 = new Student("Tommy", 23);
    ...
}

```

<p>Then, we call the <b>show_data</b> function to see the output on the screen. </p>

```
int main() {
    Student* s1 = new Student("Tommy", 23);
    s1.show_date();
    ...    
}

```

<p> So, after creating our first object, we want to use a copy constructor to create another one. In C++, the compiler has an implicit copy constructor. </p>

```
Student* s2(s1);

```

<p> What do you think the memory address is of both objects?</p>

```
 Student* s1 = new Student("Tommy", 23);
    s1->show_data();
    std::cout << s1 << "\n";

    Student* s2(s1);
    s2->show_data();
    std::cout << s2 << "\n";

```

<p> If you said that they have the same memory address, you are correct! </p>

<p> Here, we used C++'s compiler-generated copy constructor. </p>

<p> When we run our program, we see that both objects share the same memory address after using the compiler-generated copy constructor. This is known as a <b>shallow copy</b></p>. 

<p><b>Example 2: Deep Copy</b></p>


![carbon(14).png](https://cdn.hashnode.com/res/hashnode/image/upload/v1615146029441/Y_3c7f4oW.png)

<p><b>Let's break this down: </b></p>

<p> In the Student class, we changed <b>int age</b> to a pointer variable <b>int* age</b></p>


```
Student class {
private:
    std::string name;
    int* age;
....
``` 

<p> Next, in our constructor, we create a new int with our age variable. This is because our age variable is a pointer in our Student class.</p>


``` 
Student(){
    age = new int;
...
``` 

<p> After this, we also add the pointer to <b>this->age = age</b> in our <b>set_dimensions</b> function because our age variable is not a pointer in our class. </p>


```
void set_dimensions(std::string name, int age) {
    this->name = name;
    *this->age = age;
``` 

<p> After that, then we move on to creating our own custom copy constructor</p>


```
Student(Student& other) {
    name = other.name;
    age = new int;
    *age = *(other.age);

}
``` 

<p> Here, we are creating a new int variable of age and creating a pointer for it. We are setting that pointer to the age of the new object that will be created. This creates a new memory address for us when we call this copy constructor. This is known as a <b>deep copy</b></p>

<p> Lastly, we need to create our own destructor as well. Whenever we allocate memory, we must also deallocate that memory as well. If we don't, it will be holding up memory which is negatively impacting our performance.</p>


```
~Student(){
    delete age;
    std::cout << std::endl;
    std::cout << "Destructor Called...." << std::endl;
}

``` 

<h2><i>Shallow Copy vs Deep Copy</i></h2>

<p>When you let the compiler implicitly create a copy constructor, under the hood, it is a <b>shallow copy</b>. It takes all the data from one object and copies it to another referencing the same memory address.</p>

<p>This may be problematic because if you delete one copied object, it will also delete the other object because they both share the same memory address.</p>

<p>So, when we create our own custom copy constructor, we are doing a <b>deep copy</b>. This gives the new copied object a unique memory address. It is no longer referencing the same memory address. Therefore, If you delete this object, it will not impact any others that you copied it from. </p>