深拷贝和浅拷贝的区别是什么

浅拷贝就比如像引用类型,而深拷贝就比如值类型。
浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。
深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是value(值)对象,如预定义类型int32,double,以及结构(struct),枚举(enum)等。

浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:
class a { public: a(int _data) : data(_data){} a(){}
private: int data; };
int main() { a a(5), b = a; // 仅仅是数据成员之间的赋值 }
这一句b = a;就是浅拷贝,执行完这句后b.data = 5;
如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别,但当对象中有这些资源时,例子:
class a { public: a(int _size) : size(_size){data = new int[size];} // 假如其中有一段动态分配的内存 a(){}; ~a(){delete [] data;} // 析构时释放资源
private: int* data; int size; }
int main() { a a(5), b = a; // 注意这一句 }
这里的b = a会造成未定义行为,因为类a中的复制构造函数是编译器生成的,所以b = a执行的是一个浅拷贝过程。我说过浅拷贝是对象数据之间的简单赋值,比如:
b.size = a.size; b.data = a.data; // oops!
这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经被释放过的内存再释放一次。
对同一块动态内存执行2次以上释放的结果是未定义的,所以这将导致内存泄露或程序崩溃。
所以这里就需要深拷贝来解决这个问题,深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。如:
class a { public: a(int _size) : size(_size){data = new int[size];} // 假如其中有一段动态分配的内存 a(){}; a(const a& _a) : size(_a.size){data = new int[size];} // 深拷贝 ~a(){delete [] data;} // 析构时释放资源
private: int* data; int size; }
int main() { a a(5), b = a; // 这次就没问题了 }
总结:
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。

浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值。但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件。。当值拷贝的时候,两个对象就有用共同的资源,同时对资源可以访问,这样就会出问题。深拷贝就是用来解决这样的问题的,它把资源也赋值一次,使对象拥有不同的资源,但资源的内容是一样的。对于堆资源来说,就是在开辟一片堆内存,把原来的内容拷贝。
如果你拷贝的对象中引用了某个外部的内容(比如分配在堆上的数据),那么在拷贝这个对象的时候,让新旧两个对象指向同一个外部的内容,就是浅拷贝;如果在拷贝这个对象的时候为新对象制作了外部对象的独立拷贝,就是深拷贝
引用和指针的语义是相似的,引用是不可改变的指针,指针是可以改变的引用。其实都是实现了引用语义。
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。

浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:
class a { public: a(int _data) : data(_data){} a(){}
private: int data; };
int main() { a a(5), b = a; // 仅仅是数据成员之间的赋值 }
这一句b = a;就是浅拷贝,执行完这句后b.data = 5;
如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别,但当对象中有这些资源时,例子:
class a { public: a(int _size) : size(_size){data = new int[size];} // 假如其中有一段动态分配的内存 a(){}; ~a(){delete [] data;} // 析构时释放资源
private: int* data; int size; }
int main() { a a(5), b = a; // 注意这一句 }
这里的b = a会造成未定义行为,因为类a中的复制构造函数是编译器生成的,所以b = a执行的是一个浅拷贝过程。我说过浅拷贝是对象数据之间的简单赋值,比如:
b.size = a.size; b.data = a.data; // oops!
这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经被释放过的内存再释放一次。
对同一块动态内存执行2次以上释放的结果是未定义的,所以这将导致内存泄露或程序崩溃。
所以这里就需要深拷贝来解决这个问题,深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。如:
class a { public: a(int _size) : size(_size){data = new int[size];} // 假如其中有一段动态分配的内存 a(){}; a(const a& _a) : size(_a.size){data = new int[size];} // 深拷贝 ~a(){delete [] data;} // 析构时释放资源
private: int* data; int size; }
int main() { a a(5), b = a; // 这次就没问题了 }
总结:
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。


香味扑鼻 美味营养 芝麻仁
酸性玻璃胶
PWM电子螺丝厂家_PWM电子螺丝_宏领五金
图书馆室外小型气象站监控
批发普通铰链
深拷贝和浅拷贝的区别是什么
液晶电视机模具 价格行情 外壳报价
腊肉烟熏炉 四川腊肉腊肠烟熏设备 腊肉烘干烟熏炉
惠州新宏基码头砖广场码头砖水泥码头砖
广东供应装修装潢香槟金铝方通-凹槽U型铝方通“崇天匠”品牌
供应D-色氨酸
卧式棒销型砂磨机厂家 供应商卧式棒销型磨砂机
供应安全阀消声器
供应镍阳极、镍电极宝鸡隆盛生产厂家
四面超市立柱自动焊机,德本自动化
咸阳仿古建筑生产
供应全自动德国orbimatic 管管焊接电源300 CA
酒店专用醇基灶具河南天之诚商贸
手持单兵终端批发价格 深圳华讯通信集群调度系统
凹版印刷机,制袋机,吹膜机,瑞安机械,造粒机