C++面试题之浅拷贝和深拷贝的区别「建议收藏」

C++面试题之浅拷贝和深拷贝的区别「建议收藏」先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。先看一个例子,有一个学生类,数据成员时学生的人数和名字:#include<iostream>usingnamespacestd;classStudent{private: intnum; c…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

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

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

#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;
}

C++面试题之浅拷贝和深拷贝的区别「建议收藏」
       执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!

C++面试题之浅拷贝和深拷贝的区别「建议收藏」

 

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

 

C++面试题之浅拷贝和深拷贝的区别「建议收藏」

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

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

#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;
}

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

 

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

 

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

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

 

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/186966.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • opencv之打开摄像头、边缘检测

    按q退出if__name__==’__main__’:cap=cv2.VideoCapture(0)#设置摄像头0是默认的摄像头如果你有多个摄像头的话呢,可以设置1,2,3….whileTrue:#进入无限循环ret,frame=cap.read()#将摄像头拍到的图像作为frame值cv2….

  • 瓦片地图拼接_开源瓦片地图

    瓦片地图拼接_开源瓦片地图瓦片地图(TiledMap)瓦片地图(TileMap)不但生成简单,并且可以灵活的用于Cocos2d-x引擎。不论你的游戏是角色扮演游戏,平台动作游戏或仿打砖块游戏,这些游戏地图可以使用开源的瓦片地图编辑器TiledMapEditor生成并保存为TMX文件格式,被Cocos2d-x支持。TMX瓦片地图格式Cocos2d支持被Tiled创建的地图文件(TMX)。Tiled的2个版本…

    2022年10月22日
  • MySQL配置文件路径

    MySQL配置文件路径一、文件名和路径1.Linux中:/etc/my.cnf2.windows中:C:\ProgramData\MySQL\MySQLServer5.7\my.ini二、常见问题:1.windows下mysql配置文件my.ini的位置(1)找到“服务”,搜索MySQL(2)右击属性查看位置可以看到在可执行文件的路径是C:\ProgramData\MySQL\MySQLServer5.7\my.ini,即mysql的配置文件在该目录下。2.c盘没有ProgramData这个文件夹

  • Google凭借Buzz进军社交网络

    Google凭借Buzz进军社交网络《纽约时报》网络版今日发表分析文章称,谷歌周二发布社交网络工具GoogleBuzz,望借此与Facebook、Twitter等社交网络行业巨头竞争。     以下是文章主要内容:  面对不计其数的社交网络服务而不知所措?谷歌愿意帮忙——再多给你一个“选择”。谷歌周二发布GoogleBuzz,用户又将多一个传递信息与想法的平台。  不出预料,GoogleBuzz

    2022年10月15日
  • 进程调度与进程切换_模式切换和进程切换有什么区别

    进程调度与进程切换_模式切换和进程切换有什么区别从今天开始,我们将要开启一个新的系列【闪耀计划】,没错!这是今年上半年的一整个系列计划!本专题目的是通过百天刷题计划,通过题目和知识点串联的方式,完成对计算机操作系统的复习和巩固;同时还配有专门的笔记总结和文档教程哦!想要搞定,搞透计算机操作系统的同学,本专栏将会通过模块化的分类,刷够1000道题,为大家提供点对点的考点相关知识轰炸!值得注意的是,本专栏将会通过教程+课后习题的方式来进行巩固教学,课后习题的题量也是算入总题数的哦!

    2022年10月20日
  • SpringBoot集成redis「建议收藏」

    SpringBoot集成redis「建议收藏」今天,日月在这里教大家如何使用springBoot集成redis,说实话比较简单,网上也有大把的教程。先套用一下网上的简介。定义REmoteDIctionaryServer(Redis)是一个由SalvatoreSanfilippo写的key-value存储系统。Redis是一个开源的使用ANSIC语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号