先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。

先看一个例子,有一个学生类,数据成员时学生的人数和名字:

#include <iostream>
using namespace std;class Student
{
private:int num;char *name;
public:Student();~Student();
};Student::Student()
{name = new char(20);cout << "Student" << endl;}
Student::~Student()
{cout << "~Student " << (int)name << endl;delete name;name = NULL;
}int main()
{{// 花括号让s1和s2变成局部对象,方便测试Student s1;Student s2(s1);// 复制对象}system("pause");return 0;
}


       执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!

这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。

所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。

添加了自己定义拷贝构造函数的例子:

#include <iostream>
using namespace std;class Student
{
private:int num;char *name;
public:Student();~Student();Student(const Student &s);//拷贝构造函数,const防止对象被改变
};Student::Student()
{name = new char(20);cout << "Student" << endl;}
Student::~Student()
{cout << "~Student " << (int)name << endl;delete name;name = NULL;
}
Student::Student(const Student &s)
{name = new char(20);memcpy(name, s.name, strlen(s.name));cout << "copy Student" << endl;
}int main()
{{// 花括号让s1和s2变成局部对象,方便测试Student s1;Student s2(s1);// 复制对象}system("pause");return 0;
}


        执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
 总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
再说几句:
当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。

3.浅拷贝带来问题的本质在于析构函数释放多次堆内存,使用std::shared_ptr,可以完美解决这个问题。

关于std::shared_ptr的原理和实现可参考:C++笔试题之smart pointer的实现

一个完整的自定义类实现可参考:C++笔试题之String类的实现

参考链接:https://www.cnblogs.com/always-chang/p/6107437.html

C++面试题之浅拷贝和深拷贝的区别相关推荐

  1. Python 赋值、浅拷贝、深拷贝的区别?

    http://songlee24.github.io/2014/08/15/python-FAQ-02/ 在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出 ...

  2. 详细解析赋值、浅拷贝和深拷贝的区别

    详细解析赋值.浅拷贝和深拷贝的区别 一.赋值(Copy) 赋值是将某一数值或对象赋给某个变量的过程,分为下面 2 部分 基本数据类型:赋值,赋值之后两个变量互不影响 引用数据类型:赋址,两个变量具有相 ...

  3. 彻底理解Python中浅拷贝和深拷贝的区别

    目录 前言 1. 浅拷贝和深拷贝的概念 2. is和==的区别 3. 赋值操作 4. copy模块里面的copy()方法 5. copy模块里面的deepcopy()方法 6.字典自带的copy方法 ...

  4. python中浅拷贝和深拷贝的区别_Python中浅拷贝和深拷贝的区别

    Python中浅拷贝和深拷贝的区别 浅拷贝和深拷贝示意图 如上图,简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝 ...

  5. python赋值浅拷贝和深拷贝的区别_python赋值、浅拷贝、深拷贝区别

    在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题.所以,在这里按个人的理解谈谈它们之间的区别. 一.赋值(assignment) 在<Py ...

  6. 前端面试:浅拷贝和深拷贝的区别?

    前些天发现了一个巨牛的人工智能学习博客,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转 那么大家晚上好,我是今天晚上的主讲老师,我是兔哥. 我们在面试中经常会被问到浅拷贝和深拷贝的区别,正好群里也 ...

  7. 浅拷贝和深拷贝的区别?如何实现深拷贝?

    一.数据类型存储 JavaScript中存在两大数据类型: 基本类型 引用类型 基本类型数据保存在在栈内存中 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用(也叫作IP ...

  8. 将对象拷贝一份备用,改变原对象的属性时,为啥备份数据也改变了?(赋值、浅拷贝和深拷贝的区别)

    前言 前两天在写代码时碰到一个很奇怪的问题,我有一个对象person = {name: ''tianxin, age: 18};,我需要将person目前的数据拷贝一份备用let copyPerson ...

  9. 浅拷贝与深拷贝的区别(详解)

    浅拷贝与深拷贝的区别 html 浅拷贝与深拷贝 一.数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型. 基 ...

最新文章

  1. 应对618,京东到家订单系统高可用架构的迭代实战
  2. Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例
  3. 深入理解Java虚拟机——java内存区域与内存溢出异常(一)
  4. 垂直拆分后,遇到瓶颈,数据水平拆分
  5. Linux 字符设备驱动结构(二)—— 自动创建设备节点
  6. nodejs操作sqlserver数据_nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例...
  7. Python字典中 get() 函数的使用
  8. 工作日志模板_生产运行部操作日志“电子化”
  9. web开发实现火星坐标、百度坐标、WGS84坐标互相转换
  10. 网络看不到计算机和设备,网络发现已关闭,网络计算机和设备不可见。请启用网络和共享中心中的网络发现。解决方法...
  11. python tokenize()_Python tokenize-rt包_程序模块 - PyPI - Python中文网
  12. 两大主流存储架构介绍:软件定义存储与超融合
  13. 产品经理与程序员之间的孽缘发展历程
  14. React Suspense 尝鲜,处理前后端IO异步操作
  15. Hyperledger Fabric 环境搭建报错
  16. 张峥、小白谈GPT与人工智能:可能是好事,也可能不是
  17. 使用DOS重定位技术执行isqlw(SQL查询分析器)
  18. Z-Stack + OSAL操作系统
  19. VC++ Hook截取鼠标点击窗口消息的问题!全局钩子
  20. 【QQ空间】网名大全

热门文章

  1. sis防屏蔽程序_手机安全防“四害”
  2. 最近很火的支付宝领红包引导单页制作
  3. Vue 路由懒加载导航守卫keep-alive
  4. Linux 设置欢迎语
  5. 公司取名避开这3个坑,通过率或可提升99%!
  6. 全世界的人注意了,我要在兄弟连这里华丽变身了~!
  7. ASCII码表中的数字和我们运算用的纯数字有何区别?
  8. 做号者产业化运作,内容平台是放水养鱼还是清理门户?
  9. 【综合】WordPress代码的缩进与高亮处理
  10. 不想学习的时候如何逼迫自己去学习?(长文预警)