string的深浅拷贝问题
深浅拷贝
- 问题引入
- 浅拷贝
- 深拷贝
- 总结
问题引入
对于一个普通的string类:
class String {
public:String(const char* str = ""){//构造函数if (nullptr == str)str = "";_str = new char[strlen(str) + 1];strcpy(_str, str);}~String(){//析构函数if (_str) {delete[] _str;_str = nullptr;}}
private:char* _str;
};
浅拷贝
对于上述的 String 类来说,浅拷贝也就是将一个对象原封不动的复制粘贴到新的对象当中,当类中没有给定拷贝构造函数时系统会默认生成一个拷贝构造函数,但默认生成的拷贝构造函数就属于浅拷贝:
当前系统默认生成的拷贝构造函数类似于:
那么,浅拷贝是否合理存在?
由上述运行截图我们可以观察到使用系统默认生成的拷贝构造函数或是代码中展现的拷贝构造方法构造出来的对象与原对象内容地址是完全一致的,也就类似于复制粘贴了一个相同的对象,那么它会产生什么问题?
在前边类与对象章节中,我们知道了在创建的类对象使用结束之后系统会自动调用相应的析构函数来释放资源空间(先构造的后释放,后构造的先释放),因此在该类中,首先要进行释放的是 s2,后释放 s1,我们来看看现象:
不知道,读者是否发现了问题所在?
解析:
在使用 s2(s1),s1拷贝构造 s2 对象时,我们发现创建出来的 s2 对象完全是复制粘贴 s1 对象而形成的,不仅对象内容完全相同,对象的地址空间也完全相同,这就导致了两个对象是共享同一份地址空间了,故在进行析构时,产生了同一份地址空间二次释放而发生异常提示
同理,在 String 类中倘若用户没有显式定义赋值运算符重载函数,则系统会默认生成一个赋值运算符重载函数,我们来看看会有什么问题?
显然,同样产生了浅拷贝(复制粘贴),则在进行空间销毁时候定会产生空间的二次释放异常,那么我们应该如何来解决这种问题?
介绍两种技术:深拷贝(重点)、写时拷贝
深拷贝
产生浅拷贝的主要是因为在进行拷贝构造或是赋值运算符重载时,直接将就对象的内容原封不动的粘贴给新对象,因而在空间释放时形成了多次释放问题,因此深拷贝主要就是解决不同对象分配不同地址空间的问题:
String(const String& s):_str(nullptr){//s2(s1)//首先需要给s2对象开辟一份独立的新空间_str = new char[strlen(s._str) + 1];//其次将s1对象中的内容拷贝到s2空间当中strcpy(_str, s._str);}
同理,赋值运算符也是一样的:
String& operator=(const String& s){if (this != &s) //判断不是自己给自己赋值{char* tmp = new char[strlen(s._str) + 1];strcpy(tmp, s._str);delete[] _str; //释放旧空间_str = tmp;}return *this;}
显然,两个对象的地址空间是不相同的,则释放空间时不会发生同一份空间多次释放的问题。
现代新写法(注意理解):
String(const String& s):_str(nullptr){//拷贝构造函数String tmp(s._str); //采用当前对象的内容构造出一个新对象tmpswap(_str,tmp._str); //进行资源交换,将临时空间 tmp 的内容与 当前对象的内容进行交换------------临时对象在函数周期结束自动析构释放}String& operator=(String s) { //以值的方式传参,需要调用一次拷贝构造函数,构造出一个新的对象 s//赋值运算符重载if (this != &s) {swap(_str, s._str); //直接进行交换}return *this;}
总结
在类中,倘若用户没有显式定义拷贝构造函数以及赋值运算符重载函数,则编译器会自动生成一份,但在使用时属于浅拷贝会造成同一份空间多个对象共享,在对象使用结束释放空间时会发生多次释放问题产生,其次在赋值运算符重载函数中,不仅会使得多个对象共享空间,还会导致空间丢失问题:
String s1("hello"); //调用构造String s2 = "world";//使用系统默认生成的赋值运算符重载函数会导致原有的 s2 对象空间泄漏s2 = s1;
因此, 我们应该在使用时进行显式的定义,防止发生浅拷贝问题的产生
写时拷贝技术
写时拷贝技术同样是针对浅拷贝问题的解决方式
允许多个对象共享同一份地址空间以及空间中的内容,并定义一个计数器来统计当前空间所共享的对象个数,并在对象使用结束之后在析构函数内部进行计数器 - 1,当析构一个对象之后,计数器变为 0,说明当前对象是共享空间的最后一个使用者,则需要对这块空间进行释放--------------------------------但同样存在一个问题:倘若某一个对象对这块共享空间的内容进行了修改,则其他对象指向的这块共享空间内容也发生了变化
因此,写时拷贝技术是在对象需要对共享的内存空间进行修改时拷贝构造出独立的空间来进行修改,这么做就不会影响到其他对象对共享空间的访问。
ps:
博文内容为原创,欢迎各位共同学习~~
相关文章:

string的深浅拷贝问题
深浅拷贝问题引入浅拷贝深拷贝总结问题引入 对于一个普通的string类: class String { public:String(const char* str ""){//构造函数if (nullptr str)str "";_str new char[strlen(str) 1];strcpy(_str, str);}~String(){//析构函数if …...
C++中的万能头文件
目录一、什么是万能头文件?二、源码三、编译器找不到 bits/stdc.h一、什么是万能头文件? C的万能头文件是: #include <bits/stdc.h>它是一个包含了每一个标准库的头文件。 优点: 在算法竞赛中节约时间;减少了…...
Java 8 Lambda 表达式 Stream
lambda表达式和Stream流是JDK8新增加的新特性,研究本文内容或者运行本文中的demo示例必须安装并使用JDK8以上的JDK版本。demo地址:https://gitee.com/huannzi/bigdataframework/tree/master/src/main/java/com/orkasgb/java 文章目录1、什么是Lambda表达…...

【VictoriaMetrics】VictoriaMetrics单机版部署(二进制版)
1、下载安装包git路径,本文基于1.87.1版本 进入git地址 :https://github.com/VictoriaMetrics/VictoriaMetrics/tags 2、下载其中linux下的 amd64架构...

SCI论文阅读-使用基于图像的机器学习模型对FTIR光谱进行功能组识别
期刊: Analytical Chemistry中科院最新分区(2022年12月最新版):1区(TOP)影响因子(2021-2022):8.008第一作者:Abigail A. Enders通讯作者:Heather C. Allen 原文链接&…...

双11大型互动游戏“喵果总动员” 质量保障方案总结
推荐语:互动游戏是一个系统化工程,在笔者的“喵果总动员”质量方案中,可以看到为保障用户体验,我们在各个难点的解决方案, 例如:用线上压测能力支持业务及时调整各服务容量、通过强化学习覆盖游戏行业的测试…...
剑指Offer专项突击版题解一
1.整数除法 思想:不能用除法、乘法、取余,那么可以用减法完成除法的操作,但是在减去被除数的时候,可以考虑被除数<<1扩大一倍在进行减少,加快减的速率。 2.二进制加法 思想:从末尾向前遍历࿰…...

Django框架之模型
模型 当前项目的开发, 都是数据驱动的。 以下为书籍信息管理的数据关系:书籍和人物是 :一对多关系 要先分析出项目中所需要的数据, 然后设计数据库表. 书籍信息表 字段名字段类型字段说明idAutoField主键nameCharField书名 idname1西游记2三国演义…...

OSACN-Net:使用深度学习和Gabor心电图信号谱图进行睡眠呼吸暂停分类
这篇文章在之前读过一次,其主要的思路就是利用Gabor变换,将心电信号转变为光谱图进行识别研究,总体来讲,不同于其他的利用心电信号分类的算法,该论文将心电信号转换为光谱图,在此基础上,分类问题…...

使用开源实时监控系统 HertzBeat 5分钟搞定 Mysql 数据库监控告警
使用开源实时监控系统 HertzBeat 对 Mysql 数据库监控告警实践,5分钟搞定! Mysql 数据库介绍 MySQL是一个开源关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的开源关系型数据库管理系统之…...

插件 sortablejs:HTML元素可拖动排序
插件 sortablejs 用于可重新排序拖放列表的JavaScript库;关键链接:npm 地址 Github 地址 安装 npm i sortablejs引入 import Sortable from "sortablejs"HTML <ul id"items"><li>item 1</li><li>item …...

libVLC 视频裁剪
作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 裁剪是指去除图像的外部部分,也就是从图像的左,右,顶部和/或底部移除一些东西。通常在视频中,裁剪是一种通过剪切不需要的部分来改变宽高比的特殊方式。 尤其是在做视频墙时,往往需要处理多个 vlc 实例…...

LAMP架构介绍及配置
LAMP架构介绍及配置一、LAMP简介与概述1、LAMP平台概述2、LAMP各组件主要作用3、构建LAMP平台二、编译安装Apache htpd服务1、将所需软件包上传到/opt目录下2、解压以下文件3、移动两个文件并改名4、安装所需工具5、编译安装6、做软连接,使文件可执行7、优化配置文件…...

Android图形显示流程简介
注:本文缩写说明本文代码都是基于Android S一、概述本文将对从App画出一帧画面到这帧画面是如何到达屏幕并最终被人眼看到的这一过程进行简要分析,并将这其中涉及到的各个流程与其在systrace上的体现对应起来,期望最终能够让读者对Android系统…...

4.5.3 ArrayList
文章目录1.特点2. 练习:ArrayList测试3.ArrayList扩容1.特点 存在java.util包中内部是用数组结构存放数据,封装数组的操作,每个对象都有下标内部数组默认的初始容量是10,如果不够会以1.5倍的容量增长查询快,增删数据效率会低 2. 练习:ArrayList测试 package partThree;import…...

十二、Linux文件 - fseek函数讲解
目录 一、fseek函数讲解 二、fseek函数实战 一、fseek函数讲解 重定向文件内部的指针 注:光标 ---- 文件内部的指针 函数原型: int fseek(FILE *stream,long offset,int framewhere) 参数: stream:文件指针offset:…...

Python3.10新特性之match语句示例详解
这篇文章主要为大家介绍了Python3.10新特性之match语句示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪正文在Python 3.10发布之前,Python是没有类似于其他语言中switch语句的&…...

虎牙盈利能力得到改善,但监管风险对其收入产生负面影响
来源:猛兽财经 作者:猛兽财经 监管风险再次成为焦点 过去一段时间,与中概股相关的监管风险再次引起了投资者的注意,这也是正在考虑投资虎牙(HUYA)的投资者需要注意的问题。 例如,监管机构在2022…...
HBase 分布式搭建
前言: 请先确保 Hadoop 集群搭建完成。 Hadoop 完全分布式搭建(超详细)搭建环境介绍: 三台主机,一主两从,系统为 Centos 7.5。 相关组件版本信息如下: jdk1.8hadoop-3.1.3zookeeper-3.5.7hbase-2.2.3注意,以下安装教程中涉及到的路径请替换成自己的! ZooKeeper 安…...
【Python】修改枚举的取值及链式调用
author: jwensh date: 2023.02.11 文章目录枚举的取值及链式调用需求背景1. enum.key 即获取值(而不是 enum.key.value)2. 多级链式调用枚举的取值及链式调用 需求背景 测试过程中需要很多参数化的设置及编程规范要求,希望修改数据不修改代…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...