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中,浅拷贝和深拷贝是涉及对象复制的两种不同方式,它们之间的关键区别在于拷贝对象时是否复制对象所指向的数据。 正文 浅拷贝(Shallow Copy): 浅拷贝只复制对象本身,而不复制对象所指向的数据。…...
Qt QtWidgets相关问题汇总
问:在Qt QWidget中设置WindowFlags为Qt::Window导致该Widget消失了,为什么? 答:WindowFlags设置为Qt::Window,表示该widget变为window类型,需要调用QWidget::show()方法。 问:Qt中WindowFlags…...
【ubuntu22.04 文件管理器nautilus配置默认终端为alacritty】
前言 ubuntu默认的终端不能通过设置里的默认应用程序配置nautilus是ubuntu自带的文件管理器,包管理器里面只有nautilus-extension-gnome-terminal而没有提供大多终端update-alternatives工具可以修改系统的默认终端(ctrl-alt-t),但对nautilus文件管理器…...
信息化发展30
IT 治理的内涵 IT 治理作为组织上层管理的一个有机组成部分, 由组织治理层或高级管理层负责, 从组织全局的高度上对组织信息化与数字化转型做出制度安排, 体现了治理层和最高管理层对信息相关活动的关注;IT 治理强调数字目标与组…...
css溢出隐藏的五种方法
一、文本溢出 当容器中的文本内容超出容器的宽度或高度时,就会出现文本溢出的情况。下面介绍几种CSS实现文本溢出的方法。 单行文本溢出省略: 单行文本溢出省略通常用于标题等文本显示,可以通过设置white-space和text-overflow属性实现。w…...
RK3568-UART通信
RK3568-UART通信 1. 功能特点 RK3568有10个UART控制器,对应设备树里的uart0-uart9。 Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准,支持以下 功能: 包含2组64字节的 FIFO,用于接收和传输支…...
武警三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课
部队三维数字沙盘电子沙盘虚拟现实模拟推演大数据人工智能开发教程第15课 现在不管什么GIS平台首先要解决的就是数据来源问题,因为没有数据的GIS就是一个空壳,下面我就目前一些主流的数据获取 方式了解做如下之我见(主要针对互联网上的一些…...
【Linux从入门到精通】通信 | 共享内存(System V)
本篇文章接着上篇文章通信 | 管道通信(匿名管道 & 命名管道)进行讲解。本篇文章的中点内容是共享内存。 文章目录 一、初识与创建共享内存 1、1 什么是共享内存 1、2 共享内存函数 1、2、1 创建共享内存 shmget 1、2、2 ftok 生成 key 1、2、3 获取共…...
ubuntu 扩展内存挂载
一般新建虚拟机时,系统默认的空间是20G,但是当我们搭建一些环境之后,需要解压一些稍微大点的源码时内存可能不够用了,这时我们需要扩展内存。 一、硬盘扩展 首先,关闭虚拟机,在虚拟机设置中将硬盘容量扩展…...
聚观早报|小米14渲染图曝光;蚂蚁金融大模型正式发布
【聚观365】9月9日消息 小米14渲染图曝光 蚂蚁金融大模型正式发布 路特斯推出全电动轿车Emeya 上汽集团8月整车销量42.3万辆 ChatGPT网站流量连续三个月下滑 小米14渲染图曝光 高通旗下全新一代旗舰芯片骁龙8 Gen3将于10月24-26日举办的骁龙技术峰会上亮相,相…...
musl libc 动态加载:默认链接脚本
前言 当前动态链接与静态链接应用程序时,均手动指定了链接脚本 使用 musl ldso 动态加载,发现不指定 链接脚本,编译后的 动态链接与静态链的应用程序依旧可以工作 那么不指定链接脚本,应用程序就没有链接操作了?还是有个默认的链接脚本? 经过实际验证,原来 musl gcc 工具…...
快速排序(递归和非递归两种方法实现)
快速排序: 1.首先找一个基准点(一般选取最左边第一个) 2.先从后往前遍历,找到第一个小于基准值的元素; 3.再从前往后,找到第一个大于基准值的元素; 4.将这两个元素两两交换 5.当i与j相遇时…...
ApiPost7使用介绍 | HTTP Websocket
一、基本介绍 创建项目(团队下面可以创建多个项目节点,每个项目可以创建多个接口): 参数描述库(填写参数时自动填充描述): 新建环境(前置URL、环境变量很有用)&#x…...
Linux常用命令——convertquota命令
在线Linux命令查询工具 convertquota 把老的配额文件转换为新的格式 补充说明 convertquota命令用于将老的磁盘额数据文件(“quota.user”和“quota.group”)转换为新格式的文件(“quota.user”和“quota.group”)。 语法 c…...
Linux 进程基础概念-进程状态、进程构成、进程控制
目录 Linux 进程 进程基础概念 进程状态 进程的构成 进程控制 进程创建和终止 Linux 进程 参考: 「linux操作系统」进程的切换与控制到底有啥关系? - 知乎 (zhihu.com),Linux进程解析_deep_explore的博客-CSDN博客,腾讯面试…...
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的个人主页 你必须赢过,才可以说不在乎输赢 文章目录 1、Flink部署1.1 集群角色1.2 Flink集群搭建1.2.1 集群启动1.2.2 向集群提交作业 1.3 部署模式1.3.1 会话模式(Session Mode)1.3.2 单作业模式(Per-Job Mod…...
执行Django 的迁移命令报错[1193, Unknown system variable default_storage_engine]
在学习“”编写你的第一个 Django 应用程序,第2部分”时候,遇到一个问题。 执行迁移命令 python manage.py makemigrations polls 后,报错: 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) {...
海域可视化监管:浅析海域动态远程视频智能监管平台的构建方案
一、方案背景 随着科技的不断进步,智慧海域管理平台已经成为海洋领域监管的一种重要工具。相比传统的视频监控方式,智慧海域管理平台通过建设近岸海域视频监控网、海洋环境监测网和海上目标探测网络等,可实现海洋管理的数字化转型。 传统的…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
