C++面试题之浅拷贝和深拷贝的区别
先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。
先看一个例子,有一个学生类,数据成员时学生的人数和名字:
#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++面试题之浅拷贝和深拷贝的区别相关推荐
- Python 赋值、浅拷贝、深拷贝的区别?
http://songlee24.github.io/2014/08/15/python-FAQ-02/ 在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出 ...
- 详细解析赋值、浅拷贝和深拷贝的区别
详细解析赋值.浅拷贝和深拷贝的区别 一.赋值(Copy) 赋值是将某一数值或对象赋给某个变量的过程,分为下面 2 部分 基本数据类型:赋值,赋值之后两个变量互不影响 引用数据类型:赋址,两个变量具有相 ...
- 彻底理解Python中浅拷贝和深拷贝的区别
目录 前言 1. 浅拷贝和深拷贝的概念 2. is和==的区别 3. 赋值操作 4. copy模块里面的copy()方法 5. copy模块里面的deepcopy()方法 6.字典自带的copy方法 ...
- python中浅拷贝和深拷贝的区别_Python中浅拷贝和深拷贝的区别
Python中浅拷贝和深拷贝的区别 浅拷贝和深拷贝示意图 如上图,简单点说 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝 ...
- python赋值浅拷贝和深拷贝的区别_python赋值、浅拷贝、深拷贝区别
在写Python过程中,经常会遇到对象的拷贝,如果不理解浅拷贝和深拷贝的概念,你的代码就可能出现一些问题.所以,在这里按个人的理解谈谈它们之间的区别. 一.赋值(assignment) 在<Py ...
- 前端面试:浅拷贝和深拷贝的区别?
前些天发现了一个巨牛的人工智能学习博客,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转 那么大家晚上好,我是今天晚上的主讲老师,我是兔哥. 我们在面试中经常会被问到浅拷贝和深拷贝的区别,正好群里也 ...
- 浅拷贝和深拷贝的区别?如何实现深拷贝?
一.数据类型存储 JavaScript中存在两大数据类型: 基本类型 引用类型 基本类型数据保存在在栈内存中 引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用(也叫作IP ...
- 将对象拷贝一份备用,改变原对象的属性时,为啥备份数据也改变了?(赋值、浅拷贝和深拷贝的区别)
前言 前两天在写代码时碰到一个很奇怪的问题,我有一个对象person = {name: ''tianxin, age: 18};,我需要将person目前的数据拷贝一份备用let copyPerson ...
- 浅拷贝与深拷贝的区别(详解)
浅拷贝与深拷贝的区别 html 浅拷贝与深拷贝 一.数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型. 基 ...
最新文章
- 应对618,京东到家订单系统高可用架构的迭代实战
- Shiro缓存使用Redis、Ehcache、自带的MpCache实现的三种方式实例
- 深入理解Java虚拟机——java内存区域与内存溢出异常(一)
- 垂直拆分后,遇到瓶颈,数据水平拆分
- Linux 字符设备驱动结构(二)—— 自动创建设备节点
- nodejs操作sqlserver数据_nodejs基于mssql模块连接sqlserver数据库的简单封装操作示例...
- Python字典中 get() 函数的使用
- 工作日志模板_生产运行部操作日志“电子化”
- web开发实现火星坐标、百度坐标、WGS84坐标互相转换
- 网络看不到计算机和设备,网络发现已关闭,网络计算机和设备不可见。请启用网络和共享中心中的网络发现。解决方法...
- python tokenize()_Python tokenize-rt包_程序模块 - PyPI - Python中文网
- 两大主流存储架构介绍:软件定义存储与超融合
- 产品经理与程序员之间的孽缘发展历程
- React Suspense 尝鲜,处理前后端IO异步操作
- Hyperledger Fabric 环境搭建报错
- 张峥、小白谈GPT与人工智能:可能是好事,也可能不是
- 使用DOS重定位技术执行isqlw(SQL查询分析器)
- Z-Stack + OSAL操作系统
- VC++ Hook截取鼠标点击窗口消息的问题!全局钩子
- 【QQ空间】网名大全