C + + learning notes - deep copy and shallow copy

Keywords: C++

Note: the coding tool is CLion+Cygwin64

catalogue

copy constructor

assignment

Function return object

Object is passed as a function parameter

Shallow copy

Deep copy

copy constructor

        When C + + assigns a value to an object reference, returns an object from a function, or passes an object as a function parameter, it will call the copy constructor of the class to create a new object.

assignment

#include <iostream>

using namespace std;

class Student {
public:
    char *name;

    Student(char *name) : name(name) {
        cout << "Constructor" << endl;
    }

    Student(const Student &student) {
        cout << "User-Defined Copy Constructor " << endl;
        this->name = student.name;
    }
};

int main() {
    Student stu("Yes");
    Student copy = stu;
    cout << "stu.name = " << stu.name << ", copy.name = "
         << copy.name << endl;
    printf("stu Your address is%p, copy Your address is%p\n", &stu, &copy);
    return 0;
}

Output:

Constructor
 User-Defined Copy Constructor 
stu.name = Yes, copy.name = Yes
stu Your address is 0 xffffcc38, copy Your address is 0 xffffcc30

Function return object

        No effect can be demonstrated on CLion. The copy constructor is not called. It can be used on Visual Studio.

Object is passed as a function parameter

#include <iostream>
#include <cstring>

using namespace std;

class Student{
public:
    char * name;
    Student(char * name):name(name){
        printf("Constructor called\n\n");
    }
    Student(const Student & student){
        printf("Copy constructor called:\n");
        this->name = student.name;
        printf("this Your address is%p\nstudent Your address is%p\n", this, &student);
        printf("this->name Your address is%p\nstudent.name Your address is%p\n\n",
               this->name, student.name);
    }
};

void showStudent(Student student){
    cout << "showStudent In function student.name = " << student.name << endl;
    printf("showStudent In function student.name Your address is%p\n", student.name);
}

int main(){
    Student student("Catch");
    showStudent(student);
    
    cout << "main In function student.name = " << student.name << endl;
    printf("main In function student.name Your address is%p\n", student.name);
    return 0;
}

Output:

Constructor called

Copy constructor called:
this Your address is 0 xffffcc38
student Your address is 0 xffffcc30
this->name Your address is 0 x1004030f8
student.name Your address is 0 x1004030f8

showStudent In function student.name = Catch
showStudent In function student.name Your address is 0 x1004030f8
main In function student.name = Catch
main In function student.name Your address is 0 x1004030f8

        It can be seen from the address in the output content that the student in the main function and the showStudent function are not the same object because their memory addresses are different. But note that the memory address of the member attribute name of the two student objects is the same.

Shallow copy

        The default copy constructor of class and the custom copy constructor that does not use the dynamic memory opening method to create variables are shallow copies. The above cases are shallow copies.

        Shallow copies cause a problem: repeatedly freeing memory at the same address. When the member attribute of the copied object is created in the dynamic memory opening mode, it will be released in the destructor, but the copy constructor implemented in the shallow copy mode will allow the object member attribute to directly save the memory address saved by the member attribute of the copied object, resulting in that when one of the two objects is released, The member property will be released by calling the destructor, and another object will be released again. When calling the destructor, because the property has been released, it will be released repeatedly, and then an error will be reported.

Examples of errors:

#include <iostream>
#include <cstring>

using namespace std;

class Student{
public:
    char * name;
    Student(char * name){
        cout << "Constructor called" << endl;
        this->name = (char*)malloc(sizeof(char) * 10);
        strcpy(this->name, name);
    }

    Student(const Student & stu){
        cout << "Copy constructor called" << endl;
        this->name = stu.name;
    }

    ~Student(){
        cout << "Destructor called" << endl;
        free(name);
        name = NULL;
    }
};

int main(){
    Student stu("Telepathy");
    Student copy = stu;
    return 0;
}

Deep copy

        Create memory by dynamically opening up memory for the member attributes of the copy object to solve the problem of repeatedly releasing the same memory caused by shallow copy.

#include <iostream>
#include <cstring>

using namespace std;

class Student{
public:
    char * name;
    Student(char * name){
        cout << "Constructor called" << endl;
        this->name = (char*)malloc(sizeof(char) * 10);
        strcpy(this->name, name);
    }

    Student(const Student & stu){
        cout << "Copy constructor called" << endl;
//        this->name = stu.name;
        // Deep copy
        this->name = (char*) malloc(sizeof(char) * 10);
        strcpy(this->name, stu.name);
    }

    ~Student(){
        cout << "Destructor called" << endl;
        free(name);
        name = NULL;
    }
};

int main(){
    Student stu("Telepathy");
    Student copy = stu;
    return 0;
}

        The difference from the error example of shallow copy is that in the copy constructor, the way of dynamic memory opening is used instead of direct assignment.

Posted by rajivgonsalves on Fri, 12 Nov 2021 19:50:48 -0800