当前位置: 首页 > news >正文

C++ 学习之深拷贝 和 浅拷贝

前言

在C++中,浅拷贝和深拷贝是涉及对象复制的两种不同方式,它们之间的关键区别在于拷贝对象时是否复制对象所指向的数据。

正文

浅拷贝(Shallow Copy)

  • 浅拷贝只复制对象本身,而不复制对象所指向的数据。
  • 当你使用浅拷贝创建一个新对象时,它将与原始对象共享相同的数据。这意味着如果一个对象修改了共享数据,另一个对象也会受到影响,因为它们指向相同的内存位置。
  • 浅拷贝通常是通过默认的复制构造函数或赋值操作符来执行的。

深拷贝(Deep Copy)

  • 深拷贝复制对象本身以及对象所指向的数据。它创建了一个新的独立副本,而不是与原始对象共享数据。
  • 深拷贝确保原始对象和新对象是完全独立的,修改一个对象不会影响另一个对象。
  • 深拷贝通常需要自定义复制构造函数和赋值操作符,以确保数据的完全复制。

分析代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
// 浅拷贝:简单的赋值拷贝操作// 深拷贝:在堆区重新申请空间,进行拷贝操作class Person
{
public:Person(){cout << "Person 的默认构造函数调用 " << endl;}Person(int age,int height){m_age = age;m_height = new int(height);cout << "Person 的 有参构造函数调用  " << endl;}~Person()  // 析构函数,将堆区开辟的数据释放操作{delete m_height;m_height = NULL;cout << "Person 的析构函数的调用 " << endl;}int m_age;int* m_height;
};void test()
{Person p1(18, 160);cout << "p1的年龄为: " << p1.m_age << " 身高为 " << *p1.m_height << endl;Person p2(p1);cout << "p2的年龄为: " << p2.m_age << " 身高为 " << *p2.m_height << endl;
}int main()
{test();
}

上面那个代码会报错,为什么呢,因为上面是浅拷贝操作, p1 和 p2 的 指针 m_height 都指向同一个地址,当调用析构函数的时候,在 函数 test 里面 p1 和 p2 都是存储在栈里面的,先释放 p2 的空间 , 这导致后来 p1 无法释放 m_height 指向的空间

在这里插入图片描述
会产生上面的报错

我们可以通过 将

		delete m_height;m_height = NULL;

改成

if (!m_height){delete m_height;m_height = NULL;}

浅拷贝带来的问题就是 堆区内存的重复释放带来的问题

利用深拷贝操作

我们可以写 拷贝函数 ,不使用默认的构造函数来实现深拷贝

Person(const Person& p){cout << " Person 的 拷贝函数的调用 " << endl;m_age = p.m_age;//	m_height = p.m_height;  编译器默认实现的就是这行代码// 自己实现深拷贝操作m_height = new int(*p.m_height);}

我们来看看具体的代码实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
// 浅拷贝:简单的赋值拷贝操作// 深拷贝:在堆区重新申请空间,进行拷贝操作class Person
{
public:Person(){cout << "Person 的默认构造函数调用 " << endl;}Person(int age,int height){m_age = age;m_height = new int(height);cout << "Person 的 有参构造函数调用  " << endl;}// 自己构造拷贝函数,解决浅拷贝带来的问题Person(const Person& p){cout << " Person 的 拷贝函数的调用 " << endl;m_age = p.m_age;//	m_height = p.m_height;  编译器默认实现的就是这行代码// 自己实现深拷贝操作m_height = new int(*p.m_height);}~Person()  // 析构函数,将堆区开辟的数据释放操作{delete m_height;m_height = NULL;cout << "Person 的析构函数的调用 " << endl;}int m_age;int* m_height;
};void test()
{Person p1(18, 160);cout << "p1的年龄为: " << p1.m_age << " 身高为 " << *p1.m_height << endl;Person p2(p1);cout << "p2的年龄为: " << p2.m_age << " 身高为 " << *p2.m_height << endl;
}int main()
{test();
}

这样 p1 和 p2 的 m_height 指向的堆的内存地址就不一样了,代码就不会报错了

相关文章:

C++ 学习之深拷贝 和 浅拷贝

前言 在C中&#xff0c;浅拷贝和深拷贝是涉及对象复制的两种不同方式&#xff0c;它们之间的关键区别在于拷贝对象时是否复制对象所指向的数据。 正文 浅拷贝&#xff08;Shallow Copy&#xff09;&#xff1a; 浅拷贝只复制对象本身&#xff0c;而不复制对象所指向的数据。…...

Qt QtWidgets相关问题汇总

问&#xff1a;在Qt QWidget中设置WindowFlags为Qt::Window导致该Widget消失了&#xff0c;为什么&#xff1f; 答&#xff1a;WindowFlags设置为Qt::Window&#xff0c;表示该widget变为window类型&#xff0c;需要调用QWidget::show()方法。 问&#xff1a;Qt中WindowFlags…...

【ubuntu22.04 文件管理器nautilus配置默认终端为alacritty】

前言 ubuntu默认的终端不能通过设置里的默认应用程序配置nautilus是ubuntu自带的文件管理器&#xff0c;包管理器里面只有nautilus-extension-gnome-terminal而没有提供大多终端update-alternatives工具可以修改系统的默认终端(ctrl-alt-t)&#xff0c;但对nautilus文件管理器…...

信息化发展30

IT 治理的内涵 IT 治理作为组织上层管理的一个有机组成部分&#xff0c; 由组织治理层或高级管理层负责&#xff0c; 从组织全局的高度上对组织信息化与数字化转型做出制度安排&#xff0c; 体现了治理层和最高管理层对信息相关活动的关注&#xff1b;IT 治理强调数字目标与组…...

css溢出隐藏的五种方法

一、文本溢出 当容器中的文本内容超出容器的宽度或高度时&#xff0c;就会出现文本溢出的情况。下面介绍几种CSS实现文本溢出的方法。 单行文本溢出省略&#xff1a; 单行文本溢出省略通常用于标题等文本显示&#xff0c;可以通过设置white-space和text-overflow属性实现。w…...

RK3568-UART通信

RK3568-UART通信 1. 功能特点 RK3568有10个UART控制器&#xff0c;对应设备树里的uart0-uart9。 Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准&#xff0c;支持以下 功能&#xff1a; 包含2组64字节的 FIFO&#xff0c;用于接收和传输支…...

武警三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课

部队三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课 现在不管什么GIS平台首先要解决的就是数据来源问题&#xff0c;因为没有数据的GIS就是一个空壳&#xff0c;下面我就目前一些主流的数据获取 方式了解做如下之我见&#xff08;主要针对互联网上的一些…...

【Linux从入门到精通】通信 | 共享内存(System V)

本篇文章接着上篇文章通信 | 管道通信&#xff08;匿名管道 & 命名管道&#xff09;进行讲解。本篇文章的中点内容是共享内存。 文章目录 一、初识与创建共享内存 1、1 什么是共享内存 1、2 共享内存函数 1、2、1 创建共享内存 shmget 1、2、2 ftok 生成 key 1、2、3 获取共…...

ubuntu 扩展内存挂载

一般新建虚拟机时&#xff0c;系统默认的空间是20G&#xff0c;但是当我们搭建一些环境之后&#xff0c;需要解压一些稍微大点的源码时内存可能不够用了&#xff0c;这时我们需要扩展内存。 一、硬盘扩展 首先&#xff0c;关闭虚拟机&#xff0c;在虚拟机设置中将硬盘容量扩展…...

聚观早报|小米14渲染图曝光;蚂蚁金融大模型正式发布

【聚观365】9月9日消息 小米14渲染图曝光 蚂蚁金融大模型正式发布 路特斯推出全电动轿车Emeya 上汽集团8月整车销量42.3万辆 ChatGPT网站流量连续三个月下滑 小米14渲染图曝光 高通旗下全新一代旗舰芯片骁龙8 Gen3将于10月24-26日举办的骁龙技术峰会上亮相&#xff0c;相…...

musl libc 动态加载:默认链接脚本

前言 当前动态链接与静态链接应用程序时,均手动指定了链接脚本 使用 musl ldso 动态加载,发现不指定 链接脚本,编译后的 动态链接与静态链的应用程序依旧可以工作 那么不指定链接脚本,应用程序就没有链接操作了?还是有个默认的链接脚本? 经过实际验证,原来 musl gcc 工具…...

快速排序(递归和非递归两种方法实现)

快速排序&#xff1a; 1.首先找一个基准点&#xff08;一般选取最左边第一个&#xff09; 2.先从后往前遍历&#xff0c;找到第一个小于基准值的元素&#xff1b; 3.再从前往后&#xff0c;找到第一个大于基准值的元素&#xff1b; 4.将这两个元素两两交换 5.当i与j相遇时…...

ApiPost7使用介绍 | HTTP Websocket

一、基本介绍 创建项目&#xff08;团队下面可以创建多个项目节点&#xff0c;每个项目可以创建多个接口&#xff09;&#xff1a; 参数描述库&#xff08;填写参数时自动填充描述&#xff09;&#xff1a; 新建环境&#xff08;前置URL、环境变量很有用&#xff09;&#x…...

Linux常用命令——convertquota命令

在线Linux命令查询工具 convertquota 把老的配额文件转换为新的格式 补充说明 convertquota命令用于将老的磁盘额数据文件&#xff08;“quota.user”和“quota.group”&#xff09;转换为新格式的文件&#xff08;“quota.user”和“quota.group”&#xff09;。 语法 c…...

Linux 进程基础概念-进程状态、进程构成、进程控制

目录 Linux 进程 进程基础概念 进程状态 进程的构成 进程控制 进程创建和终止 Linux 进程 参考&#xff1a; 「linux操作系统」进程的切换与控制到底有啥关系&#xff1f; - 知乎 (zhihu.com)&#xff0c;Linux进程解析_deep_explore的博客-CSDN博客&#xff0c;腾讯面试…...

Unity Animation、Animator 的使用

文章目录 1. 添加动画2. Animation2.1 制作界面2.2 制作好的 Animation 动画2.3 添加和使用事件 3. Animator3.1 制作界面3.2 一些参数解释3.3 动画参数 4. Animator中相关类、属性、API4.1 类4.2 属性4.3 API4.4 几个关键方法 5. 动画播放和暂停控制 1. 添加动画 选中待提添加…...

Flink--2、Flink部署(Yarn集群搭建下的会话模式部署、单作业模式部署、应用模式部署)

星光下的赶路人star的个人主页 你必须赢过&#xff0c;才可以说不在乎输赢 文章目录 1、Flink部署1.1 集群角色1.2 Flink集群搭建1.2.1 集群启动1.2.2 向集群提交作业 1.3 部署模式1.3.1 会话模式&#xff08;Session Mode&#xff09;1.3.2 单作业模式&#xff08;Per-Job Mod…...

执行Django 的迁移命令报错[1193, Unknown system variable default_storage_engine]

在学习“”编写你的第一个 Django 应用程序&#xff0c;第2部分”时候&#xff0c;遇到一个问题。 执行迁移命令 python manage.py makemigrations polls 后&#xff0c;报错&#xff1a; migrations.py:109: RuntimeWarning: Got an error checking a consistent migration …...

Himall商城-公共方法

目录 1 Himall商城-公共方法 1.1 /// 根据订单id获取订单项 1.2 /// 根据订单项id获取售后记录 1.3 /// 判断订单是否正在申请售后 Himall商城-公共方法 #region 公共方法 public static List<InvoiceTitleInfo> GetInvoiceTitles(long userid) {...

海域可视化监管:浅析海域动态远程视频智能监管平台的构建方案

一、方案背景 随着科技的不断进步&#xff0c;智慧海域管理平台已经成为海洋领域监管的一种重要工具。相比传统的视频监控方式&#xff0c;智慧海域管理平台通过建设近岸海域视频监控网、海洋环境监测网和海上目标探测网络等&#xff0c;可实现海洋管理的数字化转型。 传统的…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...