C++ 浅拷贝和深拷贝

目录

1. 浅拷贝

2. 深拷贝


1. 浅拷贝

        浅拷贝只是拷贝一个指针,并没有新开辟一个地址,拷贝的指针和原来的指针指向同一块地址,如果原来的指针所指向的资源释放了,那么再释放浅拷贝的指针的资源就会出现错误

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

举个栗子:

#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拷贝后会出现两个指针指向同一个内存空间。

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

2. 深拷贝

        深拷贝不仅拷贝值,还开辟出一块新的空间用来存放新的值,即使原先的对象被析构掉,释放内存了也不会影响到深拷贝得到的值。在自己实现拷贝赋值的时候,如果有指针变量的话是需要自己实现深拷贝的。

举个栗子:

#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,可以完美解决这个问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/72634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深入解析spring cloud gateway】06 gateway源码简要分析

上一节做了一个很简单的示例&#xff0c;微服务通过注册到eureka上&#xff0c;然后网关通过服务发现访问到对应的微服务。本节将简单地对整个gateway请求转发过程做一个简单的分析。 一、核心流程 主要流程&#xff1a; Gateway Client向 Spring Cloud Gateway 发送请求请求…

探索Apache Hive:融合专业性、趣味性和吸引力的数据库操作奇幻之旅

文章目录 版权声明一 数据库操作二 Hive数据表操作2.1 表操作语法和数据类型2.2 Hive表分类2.3 内部表Vs外部表2.4 内部表操作2.4.1 创建内部表2.4.2 其他创建内部表的形式2.4.3 数据分隔符2.4.4 自定义分隔符2.4.5 删除内部表 2.5 外部表操作2.5.1 创建外部表2.5.2 操作演示2.…

代码生成商业化一些思考

代码生成解决方案 生成项目代码有3大类的解决思路&#xff1a; 1.从底到上的生成&#xff0c;部分代码生成生成一行代码或者一个方法种一小块代码生成&#xff0c;ide插件代码生成基本这种思路 2.大语言模型作为软件工程不同角色agent&#xff0c;用户给出idea每个agent自动…

BFS练习1

BFS练习1 - 题目 - Daimayuan Online Judge 问题描述&#xff1a; 刚开始吓一跳&#xff0c;以为有什么更简单的呢&#xff0c;因为每一次都要走一次bfs&#xff0c;看了数据范围后&#xff0c;感觉跑一次bfs进行记录即可。 代码&#xff1a; void solve() {int a,k; cin>…

超详细的 pytest 教程(一)使用入门篇

前言 pytest到目前为止还没有翻译的比较好全面的使用文档&#xff0c;很多英文不太好的小伙伴&#xff0c;在学习时看英文文档还是很吃力。本来去年就计划写pytest详细的使用文档的&#xff0c;由于时间关系一直搁置&#xff0c;直到今天才开始写。本文是第一篇&#xff0c;主…

leetcode 1609.奇偶树

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;奇偶树 思路&#xff1a; 树的层序遍历&#xff0c;用队列辅助。用一个变量记录当前是多少层&#xff0c;以及当前层的节点个数&#xff0c;依次遍历&#xff0c;因为需要判断当前层是否严格递增或递减&#xff0c;如果正…

数据结构——带头双向循环链表

数据结构——带头双向循环链表 一、带头双向循环链表的定义二、带头双向循环链表的实现2.1初始化创建带头双向循环链表的节点2.2申请新节点2.3节点的初始化2.4带头双向循环链表的尾插2.5带头双向循环链表的头插2.6判空函数2.7带头双向循环链表的打印函数2.8带头双向循环链表的尾…

软件生命周期及流程【软件测试】

软件的生命周期 软件生命周期是软件开始研制到最终被废弃不用所经历的各个阶段。 瀑布型生命周期模型 规定了它们自上而下、相互衔接的固定次序&#xff0c;如同瀑布流水&#xff0c;逐级下落&#xff0c;具有顺序性和依赖性。每个阶段规定文档并需进行评审。 特点&#xff…

SpringMVC:从入门到精通

一、SpringMVC是什么 SpringMVC是Spring提供的一个强大而灵活的web框架&#xff0c;借助于注解&#xff0c;Spring MVC提供了几乎是POJO的开发模式【POJO是指简单Java对象&#xff08;Plain Old Java Objects、pure old java object 或者 plain ordinary java object&#xff0…

redis 5.0.x 部署

PS&#xff1a;对于使用者来说&#xff0c;Redis5.0和4.0都是一样的&#xff0c;但是redis 4.0的集群部署需要额外安装ruby的东西&#xff0c;5.0中则集成到了redis-cli&#xff0c;部署起来更方便 1.1 安装Redis 本章基于CentOS 7.9.2009编写而成&#xff0c;由于Linux发行版…

【网络知识点】三次握手和四次挥手

文章目录 一、三次握手二、四次挥手 一、三次握手 三次握手的原理如下&#xff1a; 客户端向服务器发送一个SYN&#xff08;同步&#xff09;包&#xff0c;其中包含一个随机生成的初始序列号&#xff08;ISN&#xff09;。 服务器收到SYN包后&#xff0c;会发送一个SYNACK&…

QT设计一个小闹钟

设置一个闹钟&#xff0c;左侧窗口显示当前时间&#xff0c;右侧设置时间&#xff0c;以及控制闹钟的开关&#xff0c;下方显示闹钟响时的提示语。当按启动按钮时&#xff0c;设置时间与闹钟提示语均不可再改变。当点击停止时&#xff0c;关闭闹钟并重新启用设置时间与闹钟提示…

微服务-kubernetes安装

文章目录 一、前言二、kubernetes2.1、Kubernetes (K8S) 是什么2.1.1、主要特性&#xff1a;2.2.2、传统部署方式&#xff1a;2.2.3、虚拟机部署2.2.4容器部署2.2.5什么时候需要 Kubernetes2.2.6、Kubernetes 集群架构 三、kubernetes安装3.1、主节点需要组件3.1.1、设置对应主…

【Eclipse】Project interpreter not specified 新建项目时,错误提示,已解决

目录 0.环境 1&#xff09;问题截图&#xff1a; 2&#xff09;错误发生原因&#xff1a; 1.解决思路 2.具体步骤 0.环境 windows 11 64位&#xff0c;Eclipse 2021-06 1&#xff09;问题截图&#xff1a; 2&#xff09;错误发生原因&#xff1a; 由于我手欠&#xff0c;将…

HTTPS 之fiddler抓包--jmeter请求

一、浅谈HTTPS 我们都知道HTTP并非是安全传输&#xff0c;在HTTPS基础上使用SSL协议进行加密构成的HTTPS协议是相对安全的。目前越来越多的企业选择使用HTTPS协议与用户进行通信&#xff0c;如百度、谷歌等。HTTPS在传输数据之前需要客户端&#xff08;浏览器&#xff09;与服…

【SpringMVC】RESTful风格CRUD实现

目录 一、REST简介 1.1 什么是REST? 1.2 REST风格的优点 1.3 请求方式 二、构建项目 ⭐思路分析 2.1 环境准备 2.1.1 导入相关pom依赖 2.1.2 jdbc.properties&#xff1a;配置文件 2.1.3 配置代码生成器 generatorConfig.xml 2.1.4 spring与mybatis整合的配置文件 s…

三门问题讨论

三门问题讨论 三门问题第一种第二种 三门问题 三门问题&#xff08;Monty Hall problem&#xff09;亦称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论&#xff0c;大致出自美国的电视游戏节目Let’s Make a Deal。问题名字来自该节目的主持人蒙提霍尔&#xff08;Monty Hall&…

LeetCode(力扣)46. 全排列Python

LeetCode46. 全排列 题目链接代码 题目链接 https://leetcode.cn/problems/permutations/ 代码 class Solution:def backtracking(self, nums, result, path, used):if len(path) len(nums):result.append(path[:])for i in range(len(nums)):if used[i]:continuepath.app…

云数据库知识学习——云数据库产品、云数据库系统架构

一、云数据库产品 1.1、云数据库厂商概述 云数据库供应商主要分为三类。 ① 传统的数据库厂商&#xff0c;如 Teradata、Oracle、IBM DB2 和 Microsoft SQL Server 等。 ② 涉足数据库市场的云供应商&#xff0c;如 Amazon、Google、Yahoo!、阿里、百度、腾讯…

Milvus Cloud扩展变更:为向量数据库注入前沿增强功能

在向量数据库的不断变化中,Milvus Cloud已成为一个改变游戏规则的先锋,革新了我们存储、搜索和分析复杂向量数据的方式。通过最新版本的Milvus Cloud2.3.0,引入了一系列重要的增强和修改,为更强大、更高效的向量数据库解决方案铺平了道路。在本文中,我们将深入探讨Milvus …