• 快速弄懂C++中的深拷贝和浅拷贝


    浅拷贝

    浅拷贝就是单纯拷贝指向该对象的内存,所以在进行多次浅拷贝后只是相当于多了几个指向同一个对象的指针,而深拷贝相当于完全复制了一个对象副本。浅拷贝指的是复制对象的所有成员变量的值,不管这些值是指针、基本数据类型还是其他对象,但当涉及到指针时,浅拷贝只会复制指针的值(即地址),而不是它所指向的数据,这可能会导致多个对象共享相同的数据。这与深拷贝相反,深拷贝会创建原对象指针所指向的数据的一个新副本。

    默认的拷贝构造函数和赋值运算符实现的就是浅拷贝。因此,如果你不为类提供自定义的拷贝构造函数和赋值运算符,编译器会为你提供默认的实现,这就是浅拷贝。

    以下是一个简单的浅拷贝的例子:

    #include 
    
    class ShallowCopy {
    public:
        int* data;
        
        ShallowCopy(int d) {
            data = new int(d);
        }
        
        // 使用编译器生成的默认拷贝构造函数
        // ShallowCopy(const ShallowCopy& src) = default;
    
        // 使用编译器生成的默认赋值运算符
        // ShallowCopy& operator=(const ShallowCopy& src) = default;
    
        ~ShallowCopy() {
            delete data;
        }
    };
    
    int main() {
        ShallowCopy obj1(10);
        ShallowCopy obj2 = obj1; // 这里进行了浅拷贝
    
        std::cout << *obj1.data << " " << *obj2.data << std::endl; // 输出: 10 10
    
        *obj1.data = 20;
    
        std::cout << *obj1.data << " " << *obj2.data << std::endl; // 输出: 20 20
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在上面的例子中,当obj2是通过obj1的拷贝构造函数创建的时,进行的是浅拷贝,所以obj1.dataobj2.data都指向相同的地址。因此,改变其中一个也会影响到另一个。

    注意:浅拷贝通常是不安全的,特别是当类中有动态分配的资源时。在上面的例子中,当obj1obj2都析构时,它们都会尝试释放同一块内存,这会导致未定义的行为。为了避免这种情况,你通常需要实现深拷贝或者使用智能指针来管理资源。

    深拷贝

    在C++中,深拷贝意味着当对象被拷贝时,不仅复制对象的所有成员变量值,而且还复制其指针成员变量所指向的数据。这与浅拷贝相反,浅拷贝只会复制指针的值而不是其所指向的数据,可能导致多个对象共享相同的数据。

    为了实现深拷贝,你通常需要为类提供自定义的拷贝构造函数和赋值运算符,并在其中对指针成员进行深拷贝。

    下面是一个深拷贝的示例:

    #include 
    
    class DeepCopy {
    private:
        int* data;
        
    public:
        DeepCopy(int d) {
            data = new int(d);
        }
        
        // 自定义拷贝构造函数,实现深拷贝
        DeepCopy(const DeepCopy& src) {
            data = new int(*(src.data));
        }
        
        // 自定义赋值运算符,实现深拷贝
        DeepCopy& operator=(const DeepCopy& src) {
            if (this == &src) {
                return *this;  // 处理自赋值的情况
            }
            
            delete data; // 删除当前对象的资源
    
            // 为当前对象分配新的资源,并拷贝内容
            data = new int(*(src.data));
    
            return *this;
        }
    
        ~DeepCopy() {
            delete data;
        }
    
        // Getter for demonstration purposes
        int getData() const {
            return *data;
        }
    };
    
    int main() {
        DeepCopy obj1(10);
        DeepCopy obj2 = obj1; // 使用自定义拷贝构造函数,实现深拷贝
    
        std::cout << obj1.getData() << " " << obj2.getData() << std::endl; // 输出: 10 10
    
        // 修改obj2的内容
        DeepCopy obj3(30);
        obj2 = obj3;
    
        std::cout << obj1.getData() << " " << obj2.getData() << " " << obj3.getData() << std::endl; // 输出: 10 30 30
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    在上面的例子中,深拷贝确保了当一个对象被拷贝或分配时,每个对象都有其自己独立的资源副本,这避免了多个对象共享相同的资源。

  • 相关阅读:
    《2022爱分析·银行数字化厂商全景报告》发布,菊风连续入选「视频银行」优质代表厂商
    java177-获取应用程序的路径
    C++的类与对象(三):构造函数、析构函数、对象的销毁顺序
    GPIO八种工作模式
    Pytest系列-YAML格式测试用例(8)
    Java--简介
    双指针算法_移动零_
    基于JavaSSM和微信小程序的智能二维码门禁管理系统
    【前端知识之JS】关于数据处理的手写代码汇总
    MySQL字段类型汇总及用法(超详细)
  • 原文地址:https://blog.csdn.net/weixin_49520696/article/details/134450431