首页 > 其他分享 >深拷贝和浅拷贝

深拷贝和浅拷贝

时间:2024-05-26 13:31:03浏览次数:22  
标签:int 对象 DeepCopy 拷贝 data size

在C++中,对象的拷贝可以通过浅拷贝(Shallow Copy)和深拷贝(Deep Copy)来实现。这两种拷贝方式在处理对象中的指针成员时有着根本的区别。

浅拷贝(Shallow Copy)

浅拷贝简单地复制一个对象的所有字段到另一个对象。如果对象中有指针成员,那么浅拷贝会复制指针的值,而不是指针指向的数据。这意味着,复制后的两个对象中的指针成员将指向内存中的同一个位置。因此,如果原始对象或副本修改了所指向的数据,另一个对象也会反映出这些修改。

举例
#include <iostream>
using namespace std;
class ShallowCopy {
public:
    ShallowCopy(int _size) : size(_size) { data = new int[size]; }
    int Get_Val() { return *data; }
    int *Get_Val_add() { return data; }
    void Set_Val(int value) { *data = value; } // 提供一个设置函数
    ShallowCopy() {}
    // 浅拷贝构造函数
    ShallowCopy(const ShallowCopy& _sc) : size(_sc.size) { data = _sc.data; }
    ~ShallowCopy() { delete[] data; data = NULL; }
private:
    int *data;
    int size;
};
int main() {
    ShallowCopy a(5);
    ShallowCopy b = a; // 使用浅拷贝构造函数
    b.Set_Val(10); // 修改b的数据
    cout << a.Get_Val() << endl; // 输出10,因为a和b共享同一块内存
    return 0;
}

在这个例子中,ShallowCopy的拷贝构造函数实现了浅拷贝。当创建b对象并复制a时,bdata指针和adata指向同一个内存地址。因此,修改b的数据也会影响到a

深拷贝(Deep Copy)

深拷贝不仅仅复制对象的所有字段,而且会复制指针指向的数据。对于指针成员,深拷贝会在内存中为新对象分配新的空间,并将原始对象指针指向的数据复制到这块新空间中。因此,原始对象和副本对象将拥有各自独立的内存副本,修改一个对象不会影响到另一个对象。

举例
#include <iostream>
using namespace std;

class DeepCopy {
public:
    DeepCopy(int _size) : size(_size) { data = new int[size]; }
    int Get_Val() { return *data; }
    int *Get_Val_add() { return data; }
    void Set_Val(int value) { *data = value; } // 提供一个设置函数
    DeepCopy() {}
    // 深拷贝构造函数
    DeepCopy(const DeepCopy& _dc) : size(_dc.size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = _dc.data[i];
        }
    }
    ~DeepCopy() { delete[] data; data = NULL; }
private:
    int *data;
    int size;
};

int main() {
    DeepCopy a(5);
    DeepCopy b = a; // 使用深拷贝构造函数
    b.Set_Val(10); // 通过公共接口修改b的数据
    cout << a.Get_Val() << endl; // 输出0,因为a和b有各自独立的内存副本
    return 0;
}

在这个例子中,DeepCopy的拷贝构造函数实现了深拷贝。当创建b对象并复制a时,bdata指针指向了一块新分配的内存,其内容是adata指针指向数据的副本。因此,修改b的数据不会影响到a

总结

  • 浅拷贝速度快,但可能导致数据共享问题,特别是当对象包含指针成员时。
  • 深拷贝会创建数据的完整副本,因此对象之间不会共享数据,但需要更多的内存和时间。
    在实际应用中,应根据具体需求选择合适的拷贝方式。如果对象中包含指针成员,并且每个对象需要独立的数据副本,则应实现深拷贝。如果对象中没有指针成员,或者不需要独立的数据副本,浅拷贝通常是足够的。在设计类时,如果需要自定义拷贝行为,应该显式定义拷贝构造函数和拷贝赋值运算符,以防止默认的浅拷贝造成的问题。

为了展示如何重载复制运算符以实现深拷贝,我们将修改您提供的DeepCopy类。在您的类中,我们已经有了一个深拷贝构造函数,但还没有重载复制运算符。我们将添加一个重载的复制运算符,以确保在对象赋值时进行深拷贝。
以下是修改后的例子:

#include <iostream>
using namespace std;
class DeepCopy {
public:
    DeepCopy(int _size) : size(_size) { data = new int[size]; }
    int Get_Val() { return *data; }
    int *Get_Val_add() { return data; }
    void Set_Val(int value) { *data = value; } // 提供一个设置函数
    DeepCopy() {}
    // 深拷贝构造函数
    DeepCopy(const DeepCopy& _dc) : size(_dc.size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = _dc.data[i];
        }
    }
    // 复制运算符重载
    DeepCopy& operator=(const DeepCopy& other) {
        if (this != &other) { // 防止自我赋值
            delete[] data; // 释放旧资源
            size = other.size; // 复制大小
            data = new int[size]; // 分配新资源
            for (int i = 0; i < size; ++i) {
                data[i] = other.data[i]; // 复制数据
            }
        }
        return *this; // 返回当前对象的引用
    }
    ~DeepCopy() { delete[] data; data = NULL; }
private:
    int *data;
    int size;
};
int main() {
    DeepCopy a(5);
    DeepCopy b; // 默认构造函数
    b = a; // 使用重载的复制运算符
    b.Set_Val(10); // 通过公共接口修改b的数据
    cout << a.Get_Val() << endl; // 输出随机值,因为a和b有各自独立的内存副本
    cout << b.Get_Val() << endl; // 输出10,因为b的数据被修改了
    return 0;
}

在这个修改后的例子中,我们添加了一个重载的复制运算符=。这个运算符首先检查自我赋值的情况,然后释放当前对象指向的内存,分配新的内存,并复制other对象的数据到当前对象。这样,无论何时一个DeepCopy对象被赋值给另一个对象,都会进行深拷贝,确保两个对象拥有独立的内存副本。
main函数中,我们创建了两个DeepCopy对象ab。我们首先使用默认构造函数创建b,然后使用重载的复制运算符=a赋值给b。随后,我们修改b的数据并打印ab的数据,可以看到它们各自拥有独立的内存副本。

标签:int,对象,DeepCopy,拷贝,data,size
From: https://blog.csdn.net/wanghao312/article/details/139213692

相关文章

  • 拷贝构造函数
    简介是一个特殊的构造函数,只有一个形参,该形参常用const修饰,是对该类型的引用。当定义一个新的对象并用一个同类型的对象对它进行初始化时,用显式拷贝构造函数。当该类型的对象传递给函数或从函数返回类型的对象时,用隐式拷贝构造函数。拷贝构造函数拷贝构造函数通常用于:1、通......
  • 深拷贝和浅拷贝
    在JavaScript的世界里,数据的复制分为两大类:浅拷贝(ShallowCopy)和深拷贝(DeepCopy)。理解它们之间的区别对于编写高效、稳定的代码至关重要。想象一下,如果你正驾驶着一艘太空船穿梭在数据宇宙中,浅拷贝就像是星际尘埃轻轻掠过,而深拷贝则是彻底的星系迁移。......
  • Ubuntu下(跨机)文件、文件夹的拷贝、删除、重命名、移动、备份
    同机操作拷贝命令格式:cp-r源文件目的文件1示例操作:cp-r/home/folderA/usr参数r是指连同源文件中的子目录一同拷贝,就把folderA拷贝到了usr下面2示例操作:cp-r/home/folderA/*/usr/folderA操作将文件夹/home/folderA下面的所有文件全部拷贝到了/usr/folderA......
  • Java的深浅拷贝认识
    目录浅拷贝深拷贝分辨代码里的深浅拷贝在Java中,深拷贝和浅拷贝是对象复制的两种方式,主要区别在于对对象内部的引用类型的处理上。浅拷贝定义:浅拷贝是指创建一个新的对象,但这个新对象的属性(包括引用类型的属性)仍然指向原来对象的属性。换言之,如果原对象中的属性是一个引用类型......
  • Java 中的深拷贝和浅拷贝你了解吗?
    前言Java开发中,对象拷贝是常有的事,很多人可能搞不清到底是拷贝了引用还是拷贝了对象。本文将详细介绍相关知识,让你充分理解Java拷贝。一、对象是如何存储的?方法执行过程中,方法体中的数据类型主要分两种,它们的存储方式是不同的(如下图):基本数据类型:直接存储在栈帧的局部变......
  • 文件拷贝脚本
    #include<FileConstants.au3>#include<Array.au3>Global$sourceFolder="G:\test_bak"Global$destinationFolder="G:\select"Global$listFilePath="G:\list.txt"Global$logFilePath="G:\search_log.tx......
  • 结构体中的指针&&拷贝赋值构造函数改造
    带有成员指针的结构体的拷贝1.问题使用结构体时,在析构时发生了**重复释放指针**的错误。2.原因定义了QList<结构体>,使用append添加结构体对象并未此结构体中的指针分配了空间,append会执行值拷贝,此时会创建新的副本添加进QList中,值得注意的是:append执行拷贝时并不会分配地......
  • 关于浅拷贝和深拷贝中需要注意的点
    -拷贝函数的调用时机//1.直接以创建好的对象初始化Personp1(20);Personp2(p1);//2.以值传递的方式Personp;doWork(p);//3.以值方式返回局部变量Personp1;returnp1;//局部变量,并不是返回上一行的p1,而是拷贝一个返回-情况:当成员中需要在堆上申请空间时。当构造......
  • java中的拷贝
    目录1.浅拷贝(只拷贝原对象的地址)2.深拷贝(拷贝原对象的所有值)深拷贝的方式这里说的拷贝主要是针对引用类型,而对于基本数据类型,拷贝就是直接把值给另一个对象1.浅拷贝(只拷贝原对象的地址)原对象的值发生变化,拷贝对象的值也会随之发生变化,因为原对象和拷贝对象是同一块空间/......
  • 深浅拷贝
    深浅拷贝【一】深浅拷贝问题给一个列表基于这个列表进行更改生成新列表方法1:复制对原来的列表不生效num_list=[1,2,3]num_list_new=[1,2,3]num_list_new.append(4)print(num_list)print(num_list_new)[1,2,3][1,2,3,4]方法2:用新的变量名指向原来......