做circrna的网站,宁波网站排名优化公司,视频号怎么推广直播,石家庄核酸检测为什么要用深拷贝 在C中#xff0c;当类包含堆内存指针成员时#xff0c;编译器默认的浅拷贝会引发内存重复释放、资源被非法篡改等致命问题#xff0c; 深拷贝是解决该类问题的核心手段。 浅拷贝的问题 C编译器会自动生成默认拷贝构造函数#xff0c;其逻辑为成员变量逐值…为什么要用深拷贝在C中当类包含堆内存指针成员时编译器默认的浅拷贝会引发内存重复释放、资源被非法篡改等致命问题深拷贝是解决该类问题的核心手段。浅拷贝的问题C编译器会自动生成默认拷贝构造函数其逻辑为成员变量逐值拷贝。该行为对基本数据类型无影响但对指向堆内存的指针仅拷贝内存地址而非指针指向的堆内存内容最终导致多个对象共享同一块堆内存引发程序崩溃。#includeiostream#includecstringusingnamespacestd;​classHouse{private:int*area;public:House(inta):area(newint(a)){cout构造函数执行堆内存地址(void*)areaendl;}​~House(){if(area!nullptr){deletearea;areanullptr;cout析构函数执行释放堆内存(void*)areaendl;}}​voidsetArea(inta){*areaa;}voidshowInfo()const{cout面积*area堆内存地址(void*)areaendl;}};intmain(){Househ1(120);House h2h1;// 触发默认浅拷贝仅拷贝area的地址​// 打印两个对象的信息验证指针指向同一堆内存h1.showInfo();h2.showInfo();​return0;}通过对象初始化新对象触发默认拷贝构造函数运行代码会直接崩溃核心问题为堆内存重复释放。上述代码运行时h1和h2的area指针指向同一块堆内存程序结束时析构函数会先释放h2的堆内存再释放h1的堆内存对已释放的堆内存再次执行delete触发C内存访问错误程序直接崩溃。额外问题修改h1.setArea(150)h2的面积也会被篡改因为二者共享堆内存资源。深拷贝深拷贝的核心逻辑为新对象重新分配独立的堆内存再将原对象堆内存的内容拷贝至新内存使拷贝后的对象与原对象拥有相同属性但独立的资源彼此的内存操作互不影响。仅在原有House类中添加自定义拷贝构造函数即可其余代码不变#includeiostream#includecstringusingnamespacestd;​classHouse{private:int*area;public:House(inta):area(newint(a)){cout构造函数执行堆内存地址(void*)areaendl;}​// 自定义深拷贝构造函数核心实现House(constHouseother){// 1. 为新对象分配独立的堆内存this-areanewint;// 2. 将原对象堆内存的内容拷贝至新堆内存*this-area*other.area;cout深拷贝构造函数执行新堆内存地址(void*)this-areaendl;}​~House(){if(area!nullptr){deletearea;areanullptr;cout析构函数执行释放堆内存(void*)areaendl;}}​voidsetArea(inta){*areaa;}voidshowInfo()const{cout面积*area堆内存地址(void*)areaendl;}};intmain(){Househ1(120);// 构造h1分配堆内存House h2h1;// 触发深拷贝为h2分配新的堆内存​// 打印信息验证两个对象堆内存地址不同内容相同couth1;h1.showInfo();couth2;h2.showInfo();​// 修改h1的面积验证h2不受影响h1.setArea(150);cout修改h1面积后endl;couth1;h1.showInfo();couth2;h2.showInfo();​return0;// 析构h2和h1释放各自的堆内存程序正常结束}同样的主函数逻辑深拷贝下两个对象拥有独立堆内存无重复释放问题且修改一个对象不会影响另一个。构造函数执行堆内存地址0x55f8d2a8eeb0 深拷贝构造函数执行新堆内存地址0x55f8d2a8ef00 h1面积120堆内存地址0x55f8d2a8eeb0 h2面积120堆内存地址0x55f8d2a8ef00 修改h1面积后 h1面积150堆内存地址0x55f8d2a8eeb0 h2面积120堆内存地址0x55f8d2a8ef00 析构函数执行释放堆内存0x0 析构函数执行释放堆内存0x0从结果可看出h1和h2的堆内存地址完全不同实现了资源独立修改h1的面积h2无变化避免了资源篡改析构函数正常释放各自的堆内存无重复释放问题程序正常结束。深拷贝需配合赋值运算符重载若在代码中使用赋值操作h2 h1仅自定义拷贝构造函数仍会触发浅拷贝问题需同时重载赋值运算符实现赋值操作的深拷贝。在House类中添加赋值运算符重载函数核心逻辑与深拷贝构造函数一致// 重载赋值运算符实现赋值操作的深拷贝Houseoperator(constHouseother){// 防止自赋值h1 h1if(thisother){return*this;}// 释放当前对象已有的堆内存避免内存泄漏if(this-area!nullptr){deletethis-area;}// 重新分配堆内存拷贝内容this-areanewint;*this-area*other.area;cout赋值运算符深拷贝新堆内存地址(void*)this-areaendl;return*this;}总结浅拷贝编译器默认实现仅逐值拷贝成员变量仅适用于无堆内存指针的简单类含堆内存指针时会导致多个对象共享堆内存引发重复释放内存和资源篡改。深拷贝通过自定义拷贝构造函数赋值运算符重载实现为新对象分配独立的堆内存并拷贝内容使对象资源完全独立解决浅拷贝的所有问题。使用场景当自定义类包含堆内存指针、动态数组、容器等需要手动管理的资源时必须实现深拷贝。核心原则深拷贝的本质是拷贝资源本身而非资源的地址浅拷贝则是拷贝资源地址而非资源本身。通俗易懂浅拷贝就是被复制的和复制的是同一片地址而深拷贝的话是两个不同的地址。