关于类的复制构造函数中深拷贝和浅拷贝的原理和作用

在 C++ 中,深拷贝和浅拷贝的实现方式不同,主要体现在如何处理对象内部的指针成员上。让我们详细解释一下这两种实现方式的区别、语法结构、原理和作用。

深拷贝和浅拷贝的不同实现

深拷贝

深拷贝会复制对象的所有数据成员及其指向的资源,确保每个对象拥有独立的数据。下面是深拷贝的实现:

class Deep {
public:
    int* data;

    // 构造函数
    Deep(int value) {
        data = new int(value);
    }

    // 深拷贝构造函数
    Deep(const Deep& other) {
        data = new int(*other.data); // 深拷贝
    }

    ~Deep() {
        delete data;
    }

    void display() const {
        std::cout << "Value: " << *data << std::endl;
    }
};

在深拷贝构造函数 Deep(const Deep& other) 中,data = new int(*other.data); 这行代码的作用是:

  • *other.data:解引用 other 对象的 data 指针,获取其指向的整数值。
  • new int(*other.data):动态分配一个新的 int 内存,并将解引用得到的整数值复制到这块新内存中。
  • data = new int(*other.data):将新分配的内存地址赋值给当前对象的 data 指针。

通过这种方式,深拷贝确保每个对象拥有独立的内存,即使两个对象的 data 成员指向不同的内存地址。

浅拷贝

浅拷贝仅复制对象的基本数据成员,而不复制对象内部指针或引用所指向的资源。下面是浅拷贝的实现:

class Shallow {
public:
    int* data;

    // 构造函数
    Shallow(int value) {
        data = new int(value);
    }

    // 浅拷贝构造函数
    Shallow(const Shallow& other) : data(other.data) {} // 浅拷贝

    ~Shallow() {
        delete data;
    }

    void display() const {
        std::cout << "Value: " << *data << std::endl;
    }
};

在浅拷贝构造函数 Shallow(const Shallow& other) 中,data(other.data) 这行代码的作用是:

  • other.data:获取 other 对象的 data 指针。
  • data(other.data):将 other 对象的 data 指针直接赋值给当前对象的 data 指针。

通过这种方式,浅拷贝导致两个对象的 data 成员指向同一块内存。

语法结构、原理和作用

深拷贝的语法结构
Deep(const Deep& other) {
    data = new int(*other.data);
}
  • Deep(const Deep& other):这是复制构造函数的定义,接受一个 const Deep& 类型的参数 other
  • data = new int(*other.data):这是深拷贝的核心操作,动态分配新内存并复制 other 对象的 data 指针所指向的值。

浅拷贝的语法结构
Shallow(const Shallow& other) : data(other.data) {}
  • Shallow(const Shallow& other):这是复制构造函数的定义,接受一个 const Shallow& 类型的参数 other
  • : data(other.data):这是初始化列表,直接将 other 对象的 data 指针赋值给当前对象的 data 指针。

原理
  • 深拷贝:深拷贝通过动态分配新内存并复制数据,确保每个对象拥有独立的资源。这样即使一个对象被修改或销毁,也不会影响其他对象。
  • 浅拷贝:浅拷贝直接复制指针值,导致多个对象共享同一块内存。这种方式简单但容易引发资源管理问题,如悬挂指针和重复释放内存。
作用
  • 深拷贝

    • 适用于需要独立管理资源的场景。
    • 避免了悬挂指针和重复释放内存的问题。
    • 确保数据完整性和独立性。
  • 浅拷贝

    • 适用于不涉及动态内存管理或资源共享的简单场景。
    • 更高效,因为不需要分配新内存和复制数据。
    • 需要小心管理资源,避免悬挂指针和重复释放内存。
    • 浅拷贝(Shallow Copy)

      让我们通过来举一些示例来看看具体怎么使用:
    • 浅拷贝是指在复制对象时,仅复制对象的基本数据成员,而不复制对象内部指针或引用所指向的资源。浅拷贝通常由编译器生成的默认拷贝构造函数和赋值运算符实现。

      示例代码
      #include <iostream>
      
      class Shallow {
      public:
          int* data;
      
          Shallow(int value) {
              data = new int(value);
          }
      
          // 默认拷贝构造函数
          Shallow(const Shallow& other) : data(other.data) {}
      
          ~Shallow() {
              delete data;
          }
      
          void display() {
              std::cout << "Value: " << *data << std::endl;
          }
      };
      
      int main() {
          Shallow obj1(42);
          Shallow obj2 = obj1; // 浅拷贝
      
          obj1.display();
          obj2.display();
      
          return 0;
      }
      
       

      在这个例子中,obj2 是通过浅拷贝构造函数从 obj1 创建的。由于浅拷贝仅复制指针的值,因此 obj1 和 obj2 共享同一个内存地址。当其中一个对象被销毁时,指针所指向的内存会被释放,这会导致另一个对象访问已释放的内存,进而引发未定义行为。

       

      深拷贝(Deep Copy)

      深拷贝是指在复制对象时,不仅复制对象的基本数据成员,还复制对象内部指针或引用所指向的资源。深拷贝通常需要用户自定义拷贝构造函数和赋值运算符。

      示例代码
      #include <iostream>
      
      class Deep {
      public:
          int* data;
      
          Deep(int value) {
              data = new int(value);
          }
      
          // 深拷贝构造函数
          Deep(const Deep& other) {
              data = new int(*other.data);
          }
      
          // 深拷贝赋值运算符
          Deep& operator=(const Deep& other) {
              if (this == &other) {
                  return *this;
              }
              delete data;
              data = new int(*other.data);
              return *this;
          }
      
          ~Deep() {
              delete data;
          }
      
          void display() const {
              std::cout << "Value: " << *data << std::endl;
          }
      };
      
      int main() {
          Deep obj1(42);
          Deep obj2 = obj1; // 深拷贝
      
          obj1.display();
          obj2.display();
      
          return 0;
      }
      
       

      在这个例子中,obj2 是通过深拷贝构造函数从 obj1 创建的。由于深拷贝会复制指针所指向的资源,因此 obj1 和 obj2 拥有独立的内存。当其中一个对象被销毁时,不会影响另一个对象。

       

      目的和作用

    • 资源独立性
      • 深拷贝确保每个对象拥有自己独立的资源,避免了多个对象共享同一资源导致的潜在问题。
    • 避免内存泄漏和未定义行为
      • 浅拷贝可能导致多个对象在析构时重复释放同一块内存,从而引发未定义行为或崩溃。深拷贝通过复制资源,避免了这种情况。
    • 确保数据完整性
      • 深拷贝确保每个对象的数据独立且完整,避免了由于共享资源导致的数据篡改问题。
  • 避免的错误:
    • 悬挂指针
      • 浅拷贝可能导致多个对象指向同一块内存,当其中一个对象被销毁时,其他对象的指针变为悬挂指针(指向已释放的内存)。
    • 重复释放内存
      • 浅拷贝可能导致多个对象在析构时重复释放同一块内存,进而引发程序崩溃或未定义行为。
    • 数据篡改
      • 浅拷贝可能导致多个对象共享同一块内存,修改其中一个对象的数据会影响其他对象,导致数据不一致。

总结

深拷贝和浅拷贝在对象复制时的处理方式不同,深拷贝会复制对象的所有数据成员及其指向的资源,确保每个对象拥有独立的数据;而浅拷贝仅复制对象的基本数据成员,导致多个对象共享同一块内存。深拷贝通过动态分配新内存并复制数据,避免了悬挂指针和重复释放内存的问题,而浅拷贝则更高效但需要小心管理资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值