[C++] Take you to understand deep and shallow copy in five minutes

Table of contents

copy function

shallow copy copy constructor

deep copy copy constructor

Summarize


 foreword

        Earlier we learned some basic knowledge points of C++, and introduced some key operations of String in STL. In addition to these bloggers, they also opened a new column about Linux (Linux column link). You can pay attention to it, and I will follow it later It will be updated little by little. Everyone, sit tight and hold on, it's time to drive! ! !

copy function

        Before we understand the deep and shallow copy, the blogger briefly introduces what is the copy constructor, here is just a brief introduction ( detailed introduction to copy construction )

        Is a special member function in C++, used to create a copy of the object. Its function is to initialize a new object by using the attribute values ​​​​of an existing object to realize the copy operation of the object. By defining a copy constructor, we can control the copying process of objects and ensure correct handling of classes containing pointers or dynamically allocated memory.

The definition of the copy constructor is as follows:

类名(const 类名& 对象名)
{
    // 构造函数的主体部分
    // 将对象的属性值拷贝到新对象
}


         The characteristics of the copy constructor: the copy constructor has the characteristics of automatic call in C++, the formal parameter type is a const reference, copying object members one by one, implicit call and explicit call, and needs to be customized .

shallow copy copy constructor

        Shallow copy refers to simply copying the value of a data member of an object to another object, which includes basic data types and pointers. In a shallow copy, only the address of the pointer is copied, but not the data pointed to by the pointer .

Below I use a simple code to illustrate the concept of shallow copy and copy constructor in C++:

#include <iostream>

class MyClass {
public:
  int* data;

  // 默认构造函数
  MyClass() {
    data = new int(0);
    std::cout << "Default Constructor called" << std::endl;
  }

  // 拷贝构造函数
  MyClass(const MyClass& obj) {
    data = new int(*(obj.data));
    std::cout << "Copy Constructor called" << std::endl;
  }

  // 析构函数
  ~MyClass() {
    delete data;
    std::cout << "Destructor called" << std::endl;
  }
};

int main() {
  // 创建对象a
  MyClass a;
  *(a.data) = 10;

  // 使用拷贝构造函数创建对象b
  MyClass b(a);

  // 修改对象b的值
  *(b.data) = 20;

  // 输出结果
  std::cout << "a.data: " << *(a.data) << std::endl;
  std::cout << "b.data: " << *(b.data) << std::endl;

  return 0;
}

The output is:

Default Constructor called
Copy Constructor called
a.data: 10
b.data: 20
Destructor called
Destructor called

        In the above code, we have defined a class called MyClass which contains a pointer member data of type int . In the default constructor, we create a data pointer and initialize it to 0. In the copy constructor, we create a new data pointer by copying the value of the source object's data pointer .

In the main function, we first create an object a and set its data value to 10. We then created another object b using the copy constructor and set its data value to the same value as a . Finally, we output the values ​​of a.data and b.data respectively .

        It should be noted that in the copy constructor, we need to manually allocate memory for the pointer member and copy the value of the source object pointer. This is because the default shallow copy will only copy the value of the pointer without creating new memory space. This can result in multiple pointers pointing to the same memory address, and when one of the pointers frees the memory, the other pointers will also lose the memory they refer to . Therefore, when dealing with classes that contain pointer members, it is usually necessary to implement a copy constructor and perform a deep copy (copy the data pointed to by the pointer) . This ensures that each object has its own copy of data, avoiding potential memory management issues.

deep copy copy constructor

        Deep copy refers to creating a new object in the copy constructor and copying all data members of the source object ( including the data pointed to by the pointer ). In this way, each object has an independent memory space, and modifying one object will not affect other objects.

Below I use a simple code to illustrate deep copy and copy constructor in C++:

#include <iostream>
#include <cstring>

class MyClass {
public:
  char* data;

  // 默认构造函数
  MyClass() {
    data = new char[1];
    *data = '\0';
    std::cout << "Default Constructor called" << std::endl;
  }

  // 拷贝构造函数
  MyClass(const MyClass& obj) {
    data = new char[strlen(obj.data) + 1];
    strcpy(data, obj.data);
    std::cout << "Copy Constructor called" << std::endl;
  }

  // 析构函数
  ~MyClass() {
    delete[] data;
    std::cout << "Destructor called" << std::endl;
  }
};

int main() {
  // 创建对象a
  MyClass a;
  a.data = new char[5];
  strcpy(a.data, "Hello");

  // 使用拷贝构造函数创建对象b
  MyClass b(a);

  // 修改对象b的值
  delete[] b.data;
  b.data = new char[6];
  strcpy(b.data, "World");

  // 输出结果
  std::cout << "a.data: " << a.data << std::endl;
  std::cout << "b.data: " << b.data << std::endl;

  return 0;
}

The output is:

Default Constructor called
Copy Constructor called
a.data: Hello
b.data: World
Destructor called
Destructor called

        In the above code, we defined a    class  called MyClass , which contains a   pointer member  data of type char* . In the default constructor, we    assign a char pointer to data and initialize it to an empty string. In the copy constructor, we first    allocate enough memory space  for data , and then use the strcpy   function to copy the string data of the source object.

        In  the main   function, we first create an object  a   and    allocate enough memory space for its data member, and set its value to "Hello". We then created another object  b using the copy constructor and set the value of its  data   member to the    same value as a . Finally, we modify  the data value   of  b   to ensure that each object has independent data.

        It should be noted that in the copy constructor, we need to manually allocate enough memory space for the pointer member and copy the data pointed to by the source object pointer. This ensures that each object has its own independent copy. At the same time, in the destructor, we need to release the memory space occupied by the pointer member to avoid memory leaks .

        Deep copying is important for objects that contain dynamically allocated memory, such as    memory allocated using new   or  malloc . By implementing the copy constructor of deep copy, each object can be guaranteed to have an independent memory space, avoid potential memory management problems, and improve the stability and reliability of the program .

Summarize

        This article mainly discusses the concept and usage of copy function. The article covers the introduction of two copy constructors, shallow copy and deep copy.

        Copy function: the concept and function of copy function. Shallow copy copy constructor, explaining the concept of shallow copy, that is, simply copying the value of the data member of one object to another object, introducing the implementation of the copy constructor of shallow copy in detail, providing an example, showing How to use shallow copy copy constructor. Deep copy copy constructor, explaining the concept of deep copy, that is, creating a new object in the copy constructor, and copying all the data members of the source object (including the data pointed to by the pointer), and introducing the copy constructor of deep copy in detail The implementation of , provides an example showing how to use the deep copy copy constructor.

Kind tips

        Thank you for your attention and support to the blogger's articles! While reading this article, we would like to remind you to leave your valuable comments and feedback. If you like this article, you can like, comment and share with your classmates, it will provide me with great encouragement and support. Also, I plan to continue exploring content related to this article in future updates. I will bring you more in-depth analysis of C++ and programming technical issues, application cases and interesting gameplay, etc. Please continue to pay attention to the blogger's update, don't miss any exciting content!

        Thank you again for your support and attention. We look forward to establishing a closer interaction with you and exploring the mysteries of C++, algorithms and programming together. I wish you a happy life and smooth bowel movements!

Guess you like

Origin blog.csdn.net/m0_75215937/article/details/132199773