深复制与浅复制

C++中,默认的复制构造函数只能实现浅复制。

浅复制指的是在对象复制前,只对对象中的数据成员进行简单的复制

大多数情况下"浅复制"已经能很好的工作了,但是当类的数据成员中有指针类型时,浅复制只会复制指针的值(地址),这样会导致两个成员指针指向同一块内存,从而带来数据安全方面的隐患,如需要分别用delete释放指针所指向的空间时就会出现问题。为了实现正确的复制,此时我们必须编写复制构造函数进行深复制。

深复制指的是当类的成员变量有指针类型时,复制对象时应该为指针变量重新分配一个新的内存空间,使该指针指向这个新的内存空间,避免浅复制中只复制指针的值,使两个指针指向同一块内存。

浅复制和深复制主要的区别就是复制指针时是否创建内存空间 ,如果没有创建内存只复制地址为浅复制,创建新内存并把值全部复制一份就是深复制。采用深复制的情况下,释放内存的时候就不会出现浅复制时重复释放同一内存的错误。
下面是对象采用浅复制的一个案例!

#include <iostream>
#include <string.h>
using namespace std;class Cperson{private:int m_age;char *m_name;public:Cperson(int age,char *name);~Cperson();void Print(void);
};
Cperson::Cperson(int age,char *name){m_name = new char[strlen(name)+1];if(m_name!=NULL){strcpy(m_name,name);}m_age = age;cout<<m_age<<"的构造函数"<<endl;
}
Cperson::~Cperson(){cout<<"析构姓名:"<<m_name<<endl;if(m_name!=NULL){delete []m_name;   }
}
void Cperson::Print(void){cout<<"My age is "<<m_age<<",My name is "<<m_name<<endl;
}
int main(void)
{Cperson Tom(10,"Tom");Tom.Print();Cperson Jim(Tom);Jim.Print();return 0;
}

运行结果如下:

程序运行的结果出现了错误。这是因为在执行语句

CPerson Tom(10,"TOM");

用动态开辟了一块内存,用来存放"Tom"。而在执行

Cperson Jim(Tom);

时,调用的是默认构造复制函数,实现对应数据的直接复制,即将Tom的成员(Tom.m_age,Tom.m_name)赋值给Jim相应的成员。此时,Tom.m_nameJim.m_name 指向同一块内存,然而系统并没有给 Jim.m_name 开辟相应的内存空间。执行完 Jim.Print()之后,开始执行析构函数,析构函数的执行顺序和对象构造函数的执行顺序相反,所以先执行Jim的析构函数,执行完Jim的析构函数之后,Jim.m_name 所指向的空间已经释放。接着执行Tom的析构函数,此时就会出现问题,即在释放Tom.m_name 所指向的内存空间时会出现问题,因为这段内存空间在Jim的析构函数里已经释放过了。出现这种问题的根本原因在于默认复制构造函数实现的是"浅复制",所以需要定义自己的复制构造函数实现"深复制" ,就可以避免上述问题。下面的代码进行深复制的展示:

/*对象的深复制*/
#include <iostream>
#include <string.h>
using namespace std;class Cperson{private:int m_age;char *m_name;public:Cperson(int age,char *name);Cperson(Cperson &per);~Cperson();void Print(void);
};
Cperson::Cperson(int age,char *name){m_name = new char[strlen(name)+1];if(m_name!=NULL){strcpy(m_name,name);}m_age = age;cout<<m_name<<"的构造函数"<<endl;
}
Cperson::Cperson(Cperson &per){m_name = new char[strlen(per.m_name)+1];if(m_name != NULL){strcpy(m_name,per.m_name);}m_age = per.m_age;cout<<m_name<<"的拷贝构造函数"<<endl;
}Cperson::~Cperson(){cout<<"析构姓名:"<<m_name<<endl;if(m_name!=NULL){delete []m_name;  }
}
void Cperson::Print(void){cout<<"My age is "<<m_age<<",My name is "<<m_name<<endl;
}
int main(void)
{Cperson Tom(10,"Tom");Tom.Print();Cperson Jim(Tom);Jim.Print();return 0;
}

运行结果如下:

总结:
不知道大家看完之后是否已经理解,其实浅复制与深复制之间的关系除了是否为指针变量开辟新的空间之外,还有一个理解角度就是:浅复制无需手动添加拷贝构造函数,深复制需要手动添加拷贝构造函数。

[C++]深复制与浅复制相关推荐

  1. php对象当参数传递 php深复制和浅复制

    把对象当参数传递给方法,在方法里改过对象后,影响到外面的对象  因为对象是引用传递过去的 class Book {public $name;public function __construct($n ...

  2. python列表浅复制_Python列表的深复制和浅复制示例详解

    一.深复制与浅复制 列表是Python中自带的一种数据结构,在使用列表时,拷贝操作不可避免,下面简单讨论一下列表的深复制(拷贝)与浅复制 首先看代码: l1 = [5, 4, 3, 2, 1] # 用 ...

  3. C#中的深复制和浅复制(在C#中克隆对象)

    C#中的深复制和浅复制(在C#中克隆对象) 转载于:https://www.cnblogs.com/dalovess/p/7002947.html

  4. python list 深复制_Python列表的深复制和浅复制示例详解

    免费资源网,https://freexyz.cn/ 一.深复制与浅复制 列表是Python中自带的一种数据结构,在使用列表时,拷贝操作不可避免,下面简单讨论一下列表的深复制(拷贝)与浅复制 首先看代码 ...

  5. C++学习基础七——深复制与浅复制

    C++学习基础七--深复制与浅复制 一.深复制与浅复制基本知识 深复制和浅复制,又称为深拷贝和浅拷贝. 深复制和浅复制的区别如下图1所示: 图1 图1表示的是,定义一个类CDemo,包含int a和c ...

  6. 深复制VS浅复制(MemberwiseClone方法介绍)

    MemberwiseClone方法,属于命名空间System,存在于程序集 mscorlib.dll中.返回值是System.Object.其含义是:创建一个当前object对象的浅表副本. MSDN ...

  7. Objective-C 深复制和浅复制与NSCopying协议

    1.简单复制只能实现浅拷贝:指针赋值,使两个指针指向相同的一块内存空间,操作不安全. 2. Foundation类已经遵守了<NSCopying>和 <NSMutableCopyin ...

  8. iOS 集合的深复制与浅复制

    2019独角兽企业重金招聘Python工程师标准>>> 概念 对象拷贝有两种方式:浅复制和深复制.顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针:深复制是直接拷贝整个对 ...

  9. IOS学习笔记十八(copy、mutableCopy、NSCopying、NSMutableCopy、深复制、浅复制)

    1. copy.mutableCopy方法 copy方法返回对象的不可修改的副本 mutableCopy方法返回的对象可修改的副本 1).测试demo int main(int argc, char ...

最新文章

  1. Python入门笔记之闭包
  2. elementui常用知识点总结
  3. 查看Centos7 系统位数
  4. Intel® Nehalem/Westmere架构/微架构/流水线 (7) - 存储转发增强
  5. cocos2dx实现翻书效果。
  6. 开课吧课堂-Java面试题:面向对象的特征有哪些方面?
  7. Junglescout 正版账号共享 亚马逊卖家选品必备软件 junglescout插件同步升级
  8. 入门单反相机最最基础知识新人详解
  9. python批量修改文件夹名
  10. excel 设置下拉选项(限定可选项、限定数据)
  11. Publish over SSH 插件配置
  12. MODULE_DEVICE_TABLE宏的作用
  13. Linux命令总结归纳
  14. NLP情感分析——KNN算法
  15. 免费翻译英文文献自动生成PDF双语文档小技巧
  16. 树状数组详解(附图解,模板及经典例题分析)
  17. Nexus简介及小白使用IDEA打包上传到Nexus3私服详细教程
  18. JMS createSession(false, Session.AUTO_ACKNOWLEDGE); 两个参数不同组合下的区别
  19. QT QList<T>介绍与应用、详解、使用说明、官方手册翻译
  20. 免费的视频服务器空间

热门文章

  1. 用glRotatef函数转动对象
  2. data:image图片转png与jpg,png转data:image格式。
  3. R语言 第三方软件包的下载及安装
  4. C++对接国际验证码接口DEMO示例
  5. 转载:BP(反向传播算法)公式推导及例题解析
  6. Codeforces 115B Lawnmower
  7. 向中级程序员转变必备的10个秘诀
  8. java xmpp协议_GitHub - zhengzhi530/xmpp: 基于Xmpp协议的即时通讯社交软件(客户端+服务端)...
  9. CodeBlocks调试功能快捷教程
  10. java简单程序彩票系统!