C++之深浅拷贝
一、浅拷贝
我们看下以下代码
Test.h 文件
#pragma once
#include<iostream>
using namespace std;
class Student
{
public:Student(){}~Student(){if (m_Id != nullptr){delete m_Id;m_Id = nullptr;}}Student(int id, string strName){m_Id = new int[id];m_strName = strName;}
private:int* m_Id;string m_strName;
};
Test.cpp 文件
#include"Test.h"
int main()
{Student s1(1, "zhangsan");Student s2(s1);cout << "helloworld" << endl;return 0;
}
运行:

只是简单的构造了两个类对象,最后运行却崩溃了
崩溃点是析构函数
~Student(){if (m_Id != nullptr){delete m_Id;m_Id = nullptr;}}
那么我们把这段删除掉试一试

运行:

ok 问题解决了?这样只会造成内存泄漏,并不是不释放 = 解决问题
但是这不是问题的本质
直接原因:析构函数,多次释放同一块空间,导致崩溃
根本原因:默认拷贝构造函数
是的,类的默认拷贝构造函数
Student s1(1, "zhangsan");Student s2(s1);
在类 Student 中 并没有定义拷贝构造函数,那么在 Student s2(s1); 时会调用类的默认成员函数:拷贝构造函数
而浅拷贝会导致一个结果
s1->m_Id
s2->m_Id
这两个类对象的成员变量 m_Id 的地址其实是一致的
打印各自的m_Id
void GetMemberAdd(){cout << m_Id << endl;}
s1.GetMemberAdd();s2.GetMemberAdd();
结果:

那么两个类对象调用析构函数,s1 先析构 delete m_Id 接着 s2 再次释放,那么就属于非法操作一块空间,最终导致崩溃。
有些朋友,可能说并没有出现这种情况,是的如果只是值拷贝,不涉及,指针拷贝,引用时深浅拷贝是一样的。
那么当涉及到指针、引用时则需要自己实现拷贝构造函数,实现深拷贝,避免造浅拷贝所出现的问题。
并且建议最好自己实现一下拷贝构造函数与类对象的 “=” 操作符重载
否则也是会出现以下情况

二、深拷贝
看了上述的问题,那么如何来解决浅拷贝的问题呢,这里就引入深拷贝的问题
我们直到出现问题的原因是:
s1->m_Id Address == s2->m_Id Address
那么我们在拷贝构造函数为每一个新的类对象的都动态创建一个新的 m_Id 那么就可以解决浅拷贝的问题了,看代码
Student(const Student& s){int iTemp = *(s.m_Id);m_Id = new int(iTemp);//动态申请新的空间,再赋值m_strName = s.m_strName;}

总结:深拷贝是开辟新的空间,再存储值,使用默认的拷贝构造,会将两个指针指向同一块空间(并没有开辟新的空间) 而是共用一块空间,因此在释放时会导致崩溃。
完整测试代码
Test.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Student
{
public:Student(){}~Student(){if (m_Id != nullptr){delete m_Id;m_Id = nullptr;}}Student(int id, string strName){m_Id = new int(id);m_strName = strName;}Student(const Student& s){int iTemp = *(s.m_Id);m_Id = new int(iTemp);m_strName = s.m_strName;}void GetMemberAdd(){cout << m_Id << endl;}void Print(){cout << *m_Id << endl;cout << m_strName << endl;}
private:int* m_Id;string m_strName;
};
Test.cpp
#include"Test.h"
int main()
{Student s1(1, "zhangsan");Student s2(s1);s1.Print();s2.Print();cout << "helloworld" << endl;s1.GetMemberAdd();s2.GetMemberAdd();return 0;
}
相关文章:
C++之深浅拷贝
一、浅拷贝 我们看下以下代码 Test.h 文件 #pragma once #include<iostream> using namespace std; class Student { public:Student(){}~Student(){if (m_Id ! nullptr){delete m_Id;m_Id nullptr;}}Student(int id, string strName){m_Id new int[id];m_strName s…...
CoreLocation的一切
Overview 概述 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pgnvehxf-1678717852996)(./blog_cover.png)] Core Location 提供的服务可以确定设备的地理位置、高度和方向,或者它相对于附近 iBeacon 设备的位置。 该框架使用设备上的所…...
HashMap原理
初始化 从HashMap 源码中我们可以发现,HashMap的初始化有一下四种方式 //HashMap默认的初始容量大小 16,容量必须是2的幂 static final int DEFAULT_INITIAL_CAPACITY 1 << 4; // HashMap最大容量 static final int MAXIMUM_CAPACITY 1 <&…...
STM32入门笔记(02):独立看门狗(IWDG)和窗户看门狗(WWDG)(SPL库函数版)
1.IWDG狗简介 除了始终控制器的RCC_CSR寄存器的父为标志位和备份区域中的寄存器以外,系统复位 将复位所有寄存器至它们的复位状态。 当发生以下任一事件时,产生一个系统复位: 1.NRST引脚上的 低 电平,即 外部复位;2…...
javaSE系列之方法与数组的使用
[TOC] javaSE系列之方法与数组的使用 方法的定义 方法类似于C语言中的"函数"。 方法的种类 这里方法分为有参方法也分为无参方法, 形参和实参是两个实体(这里相当于函数的传值调用和传址调用) 1.非静态方法:普通方法/…...
常用命令总结
将常用命令汇集于此,以便在忘记的时候查询,持续更新…… Git Local changes 添加名字: git config --global user.name "<你的名字>"添加邮件: git config --globa user.email "<你的邮箱>"…...
【Linux:程序地址空间--原来操作系统也喜欢画大饼】
目录 1 代码感受 2 进程地址空间 3 扩展 1 代码感受 在正式讲程序地址空间前我们先来看一段简单的代码来分析分析: 1 #include<iostream>2 #include<unistd.h>3 using namespace std;4 5 int g_val100;6 7 int main()8 {9 pid_t idfork();10 if(i…...
Python实现简单信号滤波实战
在有些项目中需要对信号进行滤波处理,尤其是在医疗的设备中如心跳、脉搏等设备的采样后进行处理。滤波的目的就是除去某些频率的信号如噪声。常见的包括有低通滤波、高通滤波、带通滤波。 低通滤波指的是去除高于某一阈值频率的信号;高通滤波去除低于某…...
Java(110):非对称加密RSA的使用(KeyPair生成密钥)
Java(110):非对称加密RSA的使用(KeyPair生成密钥) RSA 算法是一种非对称加解密算法。服务方生成一对 RSA 密钥,即公钥 私钥,将公钥提供给调用方,调用方使用公钥对数据进行加密后,服务方根据私钥进行解密。 1、RSA生…...
(Mybatis 学习【1】)整合 Mybatis 开发流程
Mybatis 整合流程 ① 添加MyBatis的依赖 ② 创建数据库表 ③ 编写pojo实体类 ④ 编写映射文件UserMapper.xml ⑤ 编写核心文件mybatis-config.xml ⑥ 编写测试类** 编写 pojo 实体类 (设计相应的数据库) Data AllArgsConstructor NoArgsConstructor public class…...
一文搞懂Kerberos
Kerberos一词来源于古希腊神话中的Cerberus——守护地狱之门的三头犬,Kerberos是为TCP/IP 网络设计的可信第三方鉴别协议,最初是在麻省理工学院(MIT)为Athena 项目而开发的。Kerberos服务起着可信仲裁者的作用,可提供安全的网络鉴别ÿ…...
Go爬虫学习笔记(三)
day3 04|敏捷之道:大型Go项目的开发流程是怎样的? 瀑布模式 流程: 市场调研需求分析产品设计研发实现集成与测试项目交付与维护 适用场景: 需求在规划和设计阶段就已经确定了,而且在项目开发周期内&…...
CASTEP参数设置(2)
虚拟试验(分子模拟) 在表征材料以及材料的相关性质时,只要是采用已有的理论加以解释 但是通常来说,需要采用已有的理论来进行设计和探索,伴随着工业软件的发展,应当选用仿真技术来缩小探索范围 传统试验V…...
浅谈对Promise的理解以及在工作中的应用
浅谈对Promise的理解以及在工作中的应用Promise的概念背景知识JavaScript的同步和异步JavaScript事件循环回调函数进行异步操作解决方案:PromisePromise 在工作中的运用创建PromisePromise封装AJAXPromise链式操作Promise.all()Promise.race()async和await总结Promi…...
开源|快速入门和理解并模拟实现GPS户外机器人的定位与导航
户外机器人的定位导航相对于需要建图的场景来说,是比较简单容易实现的,因为可以借助第三方地图完成定位,并在第三方地图中完成路径规划和下发航点等操作,实现的难题在于如何控制机器人完成步行和转弯。 这些在不引进RTK高精度定位…...
Java多线程系列--synchronized的原理
原文网址:Java多线程系列--synchronized的原理_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Java的synchronized的原理。 反编译出字节码 Test.java public class Test {private static Object LOCK new Object();public static int main(String[] args) {synchro…...
QEMU启动ARM64 Linux内核
目录前言前置知识virt开发板ARM处理器家族简介安装qemu-system-aarch64安装交叉编译工具交叉编译ARM64 Linux内核交叉编译ARM64 Busybox使用busybox制作initramfs使用QEMU启动ARM64 Linux内核前言 本文介绍采用 qemu 模拟ARM-64bit开发板(针对ARM-32bit的有另一篇文…...
Linux->进程程序替换
目录 前言: 1 程序替换原理 2 单进程替换 3 替换函数 3.1 函数使用 4 程序去替换自己的另一个程序操作方式 5 实现自己的shell 前言: 通过我们之前对于子进程的应用,我相信大家一定是能够想到创建子进程的目的之一就是为了代劳父进程执…...
最强分布式锁工具:Redisson
1 Redisson概述1.1 什么是Redisson?Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, Sorted…...
Java9-17新特性
Java9-17新特性 一、接口的私有方法 Java8版本接口增加了两类成员: 公共的默认方法公共的静态方法 Java9版本接口又新增了一类成员: 私有的方法 为什么JDK1.9要允许接口定义私有方法呢?因为我们说接口是规范,规范时需要公开…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
