[C++] deep copy & shallow copy

Preface : In C++, a "shallow copy" or "deep copy" occurs when an object is about to become a copy of another object through assignment or copying.

What is a shallow copy?

        Shallow copy means that two objects share the same memory address, that is, the address of the data member of the source object is assigned to the target object. When the source object and the target object are destroyed, the problem of repeated release will occur, causing the program to crash.

        Objects of the same type can be assigned, so that the values ​​of the member variables of the two objects are the same, and the two objects are still two independent objects. This situation is called shallow copy .

        Under normal circumstances, shallow copy does not have any side effects, but when there are pointers in the class, and the pointer points to the dynamically allocated memory space, the destructor performs dynamic memory release processing, which will cause memory problems.

 Look at the picture to understand:

Here is an example of a shallow copy:

class Person {
public:
    int mAge;
    char* pName;
    Person(const char* n, int a) : name(new char[strlen(n) + 1]), mAge(a) {
        strcpy(pName, n);
    }

    // 浅拷贝构造函数
    Person(const Person & p) : age(p.mAge), name(p.pName) {} 
};

        In the above code, we define a  Person class that contains a  char type of pointer member pName and a  int type of member mAge. In the shallow copy constructor, the address of the source object is directly assigned to the target object, which will cause the two objects to share the same memory. When one of the objects is destroyed, the pointer member variable of the other object will point to A piece of memory has been freed, causing the program to crash.

What is a deep copy?

        Deep copy means that when an object is copied, a new memory space will be opened to store data, and the content of the data member of the source object will be copied to the data member of the target object, so that there will be no problem of repeated release.

        When there is a pointer in the class, and the pointer has dynamically allocated space, and the destructor performs release processing, it is often necessary to customize the copy constructor, dynamically allocate space for the pointer, and make a deep copy .

Look at the picture to understand:

Here is an example of a deep copy:

class Person {
public:
    int mAge;
    char* pName;
    Person(const char* n, int a) : name(new char[strlen(n) + 1]), mAge(a) {
        strcpy(pName, n);
    }

    // 深拷贝构造函数
    Person(const Person & p) : age(p.mAge), name(new char[strlen(p.pName) + 1]) {
        strcpy(name, p.pName);
    } 
};

        In the above code, we use deep copy to create an object, and copy the content of the data member of the source object to the target object, preventing the problem of repeated release.

how to choose?

        When the object contains only basic data type members, you can use shallow copy; when the object contains pointer type members, you need to use deep copy.

        In practice, we need to choose different copy methods according to the specific situation. When there are pointer type members in the object, you need to ensure that the same address will not be shared when copying, otherwise you need to use deep copy. In addition, when using deep copy, you should also pay attention to freeing memory to avoid memory leaks.

        The following is an example containing a member variable of pointer type as an illustration:

class Employee {
public:
    Employee(const char* n, int a, const char* p) : name(new char[strlen(n) + 1]), age(a), position(new char[strlen(p) + 1]) {
        strcpy(name, n);
        strcpy(position, p);
    }

    ~Employee() {
        delete[] name;
        delete[] position;
    }

    // 浅拷贝构造函数
    Employee(const Employee& other) : name(other.name), age(other.age), position(other.position) {} 

    // 深拷贝构造函数
    Employee(const Employee& other) : age(other.age), name(new char[strlen(other.name) + 1]), position(new char[strlen(other.position) + 1]) {
        strcpy(name, other.name);
        strcpy(position, other.position);
    }

private:
    char* name;
    int age;
    char* position;
};

        In the above code, we define  Employee a class, which contains three member variables, including two  char types of pointer type member variables  name and  position, and one  int type of basic data type member variables  age.

        We can see that if we want to make a shallow copy, we only need to copy the address of the pointer type member variable of the source object to the pointer type member variable of the target object, but there is a problem with this is that the source object and the target object will share The memory space pointed to by the pointer, when the source object is destroyed, the pointer held by the target object will point to a memory space that has been released, which will cause the program to crash, so shallow copy is not suitable for this type of member variable.

        For objects containing pointer type member variables, the commonly used copy method is deep copy . This copy method will re-allocate a block of memory for the target object, and copy the content of the data member of the source object to the data member of the target object, thereby avoiding the problem of repeated release. In the above code, we use the deep copy method to create the target object.

Summarize:

        In the development of C++, both deep copy and shallow copy are very important concepts. Specifically, the copy method should be selected according to the type of member variable of the object, and the problem of memory release should be paid attention to when using deep copy. It is recommended to use deep copy when the object contains pointer type members; shallow copy can be used when the object only contains basic data type members.

Guess you like

Origin blog.csdn.net/crr411422/article/details/131033612