「C++之STL」关于在模拟实现STL容器中的深浅拷贝问题

文章目录

  • 前言
    • 杨辉三角
    • 深浅拷贝问题
    • 模拟实现的vector对题目杨辉三角引发的程序崩溃
    • 原因
    • 解决办法

前言

在学习STL容器中,不仅需要学会容器的使用,同时也需要了解容器的大体框架以及各个函数的模拟实现才能更好的去了解这个容器;

杨辉三角

在LeetCode中有一道这样的题目,给定一个非负整数 numRow ,生成「杨辉三角」的前 numRows 行;
[题目链接]
在这里插入图片描述
从图中可知杨辉三角的概念,即每一个数都是它上方左右两数的和,且整个三角形呈对称关系;
这题若是使用c语言的话可以直接用二维数组的思路进行作答;

//c
int** generate(int numRows, int* returnSize, int** returnColumnSizes){int** ret = malloc(sizeof(int*)*numRows); //申请返回的指针空间*returnSize = numRows; //返回行数*returnColumnSizes = malloc(sizeof(int*)*numRows); //为每一列分配空间for(int i=0;i<numRows;i++){ret[i] = malloc(sizeof(int)*(i+1));//分配每一行的个数(*returnColumnSizes)[i] = i + 1;//为第一个以及最后一个赋值ret[i][0] = 1;ret[i][i] = 1;for(int j=1;j<i;j++){ret[i][j] = ret[i-1][j-1] + ret[i-1][j];}}return ret;
}

若是使用C++的话则可以使用STL容器中的vector来模仿二维数组;

//c++
class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>>triangle(numRows);for(int i = 0;i<numRows;i++){triangle[i].resize(i+1,0);triangle[i].front() = triangle[i].back() = 1;}for(int i = 0;i<numRows;i++){for(int j = 0;j<triangle[i].size();j++){if(triangle[i][j]!=1){triangle[i][j] = triangle[i-1][j-1]+triangle[i-1][j];}}}return triangle;}
};

且其思路与C语言中的二维数组法相同;

深浅拷贝问题

[【C++】STL之String模拟实现 ]
在该篇文章中,我写出了对于类似拷贝构造或者扩容时应该进行的深浅拷贝;
在学过一段时间的C++后就能知道,在默认成员函数中存在拷贝构造函数以及赋值重载等函数;
这些默认成员函数在没有显式定义时,编译器会自动生成一个默认的对应函数;
而对于编译器自动生成的拷贝构造以及赋值重载函数,对于内置类型将会进行值拷贝,而对于自定义类型来说将会调用它的默认构造函数;
在这篇文章中对于类似扩容,拷贝构造以及赋值重载函数,采用的方法都是:

开辟一块新的空间,再将原先的数据使用memcpy函数或者在string中使用的strcpy函数拷贝到新的空间;

拷贝构造
//拷贝
My_string::string::string(const string& str):_str(new char[str._size+1]),_size(str._size),_capacity(str._size)
{memcpy(_str, str._str,str._size);_str[_size] = '\0';
}
扩容
 //扩容void My_string::string::reserve(size_t n){if (n > _capacity) {char* temp = new char[n+1];//多开1的空间确保n为有效数据的空间而+1为给'\0'的无效空间strcpy(temp, _str);_capacity = n;delete[]_str;_str = temp;}}
赋值重载
My_string::string& My_string::string::operator=(const string& str)//赋值操作符重载{if (this != &str) {char* temp = new char[str._capacity+1];strcpy(temp, str._str);delete[]_str;_str = temp;_size = str._size;_capacity = str._capacity;}return *this;}

模拟实现的vector对题目杨辉三角引发的程序崩溃

同时,我模拟实现了一个vector容器,这个容器的完成程度暂且不提,在这里的拷贝构造函数,扩容以及赋值重载依旧按照模拟实现string那样使用memcpy进行原数据拷贝到新空间的方法;

//拷贝构造vector(const vector<T>&v){T* tmp = new T[v.size()];_start = tmp;memcpy(tmp,v._start,sizeof(T)*v.size());_finish = _end_of_storage = _start + v.size();}/*扩容reserve*/void reserve(size_t n){if(n>capacity()){size_t count = size();T* tmp = new T[n];memcpy(tmp,_start,sizeof(T)*count);delete[]_start;_start = tmp;_finish = _start+count;_end_of_storage = _start+n;}}

而使用这种方法对杨辉三角题目进行测试时,程序将崩溃;

在这里插入图片描述

而程序崩溃的原因为析构函数;
在这里插入图片描述

原因

当程序在析构函数处崩溃且析构函数并没有其他问题的时候,应该及时将问题的思路转变到对象的深浅拷贝问题;
而这里出的错误正是使用memcpy函数进行拷贝从而造成的浅拷贝;
那为什么在这里使用memcpy时将会造成浅拷贝;
在模拟这些成员函数中,一般优先会想到的类型为内置类型,即语言标准指定,编译器自带的类型;
如果为vector< int >,vector< char >将可以使用memcpy进行拷贝;
但是vector这类的容器为一种类模板,对于类模板来说,其给的模板参数不一定一定就是内置类型,也有可能出现自定义类型;
就如使用vector< vector< int > >来说,最外层的模板参数为一个自定义类型,而内层的模板参数为一个内置类型int;

在这里插入图片描述
而如果在这里使用了memcpy进行原数据到新空间的拷贝将会怎么做;
在这里插入图片描述
表面上这里进行了拷贝,但实际上,进行了深拷贝的只有最外层;
对于内层而言只是使用了memcpy将对应的对象进行拷贝;
也就是说,这里出现了指针指向同一块空间的问题;

在这里插入图片描述
而若是在这种情况下则会出现重复析构的问题;


解决办法

在这种情况下只能摒弃以往的使用memcpy进行数据拷贝,并使用赋值进行拷贝;
以拷贝构造为例:

vector(const vector<T>& v){_start = new T[v.size()];for(size_t i = 0;i<v.size();++i){_start[i] = v._start[i];//若是自定义类型将会去调用它的赋值重载}_finish = _start + v.size();_end_of_storage = _start + v.capacity();
}

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

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

相关文章

jvm垃圾收集算法

简介 由于《分代收集理论》和不同垃圾收集算法&#xff0c;Java堆应该被划分为不同区域&#xff0c;一般至少会把Java堆划分为新生代&#xff08;Young Generation&#xff09;和老年代&#xff08;Old Generation&#xff09;两个区域。 垃圾收集器可以只回收其中某一个或者…

单片机外设-串口(UART)详情

目录 学习UART要先认识一些基础知识 一&#xff1a;什么是串行、并行通信&#xff1f; &#xff08;1&#xff09;串行通信 串行通信概念&#xff1a; 串行通信的特点&#xff1a; &#xff08;2&#xff09;并行通信 并行通信概念&#xff1a; 并行通信特点&#xff1…

【Linux】Linux远程访问Windows下的MySQL数据库

1.建立Windows防火墙规则 首先需要开放windows防火墙&#xff0c;针对3306端口单独创建一条规则&#xff0c;允许访问。 打开windows安全中心防火墙与保护&#xff0c;点击高级设置 进入之后&#xff0c;点击入站规则&#xff0c;新建一条规则 新建端口入站规则 端口填写330…

问题 - 谷歌浏览器 network 看不到接口请求解决方案

谷歌浏览器 -> 设置 -> 重置设置 -> 将设置还原为其默认值 查看接口情况&#xff0c;选择 All 或 Fetch/XHR&#xff0c;勾选 Has blocked cookies 即可 如果万一还不行&#xff0c;卸载浏览器重装。 参考&#xff1a;https://www.cnblogs.com/tully/p/16479528.html

C# 字符串和正则表达式

C# 字符串和正则表达式 System.String 类StringBuilder 成员格式化字符串正则表达式 System.String 类 StringBuilder 成员 格式化字符串 正则表达式

python加入环境变量

今天没事玩了会python,之前都是在windows下玩的&#xff0c;没什么问题。 今天要在dos窗口下运行python&#xff0c;却发现运行不了。而且在python安装目录下是可以运行的&#xff0c;于是我知道了我在安装python的时候没选择加入环境变量。我对windows还有是有定了解的&#x…

算法与数据结构-Trie树

文章目录 什么是“Trie 树”&#xff1f;如何实现一棵 Trie 树&#xff1f;Trie 树真的很耗内存吗&#xff1f;Trie 树与散列表、红黑树的比较 什么是“Trie 树”&#xff1f; Trie 树&#xff0c;也叫“字典树”。顾名思义&#xff0c;它是一个树形结构。它是一种专门处理字符…

你真的会自动化吗?Web自动化测试-PO模式实战,一文通透...

前言 PO模式 Page Object(简称PO)模式&#xff0c;是Selenium实战中最为流行&#xff0c;并且是自动化测试中最为熟悉和推崇的一种设计模式。在设计自动化测试时&#xff0c;把页面元素和元素的操作方法按照页面抽象出来&#xff0c;分离成一定的对象&#xff0c;然后再进行组…

《DATASET CONDENSATION WITH GRADIENT MATCHING》

本文提出了一种用于数据效率学习的训练集合成技术&#xff0c;称为“数据集凝聚”(Dataset)&#xff0c;它学习将大数据集压缩成一个小的信息合成样本集&#xff0c;用于从头开始训练深度神经网络。我们将这个目标表述为在原始数据和合成数据上训练的深度神经网络权值的梯度之间…

提高效率!掌握项目管理工具中任务优先级的使用技巧

在项目管理中&#xff0c;我们经常会遇到一些具有强制依赖关系的任务。这些任务之间的关系是绝对的&#xff0c;并且毫无疑问必须首先完成什么。例如&#xff0c;您必须先设计一个产品&#xff0c;然后才能构建它&#xff0c;并且必须先构建它&#xff0c;然后才能绘制它。然而…

汽车电子——产品标准规范汇总和梳理(信息安全)

文章目录 前言 一、整车 二、充电接口 三、诊断接口 四、远程接口 五、实施指南 总结 前言 见《汽车电子——产品标准规范汇总和梳理》 一、整车 《GB/T 40861-2021 汽车信息安全通用技术要求》 《GB XXXXX—XXXX 汽车整车信息安全技术要求》 《GB/T 41871-2022 信息…

Goby 漏洞发布|Cockpit 平台 upload 文件上传漏洞(CVE-2023-1313)

漏洞名称&#xff1a;Cockpit 平台 upload 文件上传漏洞&#xff08;CVE-2023-1313&#xff09; English Name&#xff1a; Cockpit File Upload Vulnerability(CVE-2023-1313) CVSS core:7.2 影响资产数&#xff1a;3185 漏洞描述&#xff1a; Cockpit 是一个自托管、灵活…

基于Spring Boot的宠物咖啡馆平台的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 看护师信息管理 宠物寄养管理 健康状况管理 点单 宠物体验 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已…

需求堆积,如何排序产品优先极

面对堆积的产品需求&#xff0c;到底该如何排序优先极呢&#xff1f; 需求排期的目标 在谈具体的排期方法之前&#xff0c;有必要先探讨一下——合理的需求排期应该达到什么的目标呢&#xff1f;如果站在与项目相关的利益人员的角度来看&#xff0c;至少应该使以下四方面的收…

基于SpringBoot+Bootstrap的旅游管理系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 登录模块的实现 景点信息管理界面 订票信息管理界面 用户评价管理界面 用户管理界面 景点资讯界面 系统主界面 用户注册界面 景点信息详情界面 订票信息界面 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言…

基于SpringBoot网上超市的设计与实现【附万字文档(LW)和搭建文档】

主要功能 前台登录&#xff1a; 注册用户&#xff1a;用户名、密码、姓名、联系电话 用户&#xff1a; ①首页、商品信息推荐、商品资讯、查看更多 ②商品信息、商品详情、评论、点我收藏、添加购物车、立即购买 ③个人中心、余额、点我充值、更新信息、我的订单、我的地址、我…

ubuntu 20 安装 CUDA

1. 查看需要安装的cuda版本 nvidia-smi cuda的版本信息如下图所示 2. 去官网下载对应版本的CUDA 官网&#xff1a;CUDA Toolkit Archive | NVIDIA Developer 弹出以下界面&#xff0c;依次点击以下按钮 得到以下内容&#xff1a; 复制下载链接&#xff0c;下载cuda11到本…

嵌入式Linux应用开发-基础知识-第十七章异常与中断的概念及处理流程

嵌入式Linux应用开发-基础知识-第十七章异常与中断的概念及处理流程 第十七章 异常与中断的概念及处理流程17.1 中断的引入17.1.1 妈妈怎么知道孩子醒了17.1.2 嵌入系统中也有类似的情况 17.2 中断的处理流程17.3 异常向量表17.4 参考资料 第十七章 异常与中断的概念及处理流程…

WPF绑定单变量Binding和绑定多变量MultiBinding 字符串格式化 UI绑定数据,数据变化自动更新UI,UI变化自动更新数据

UI绑定数据&#xff0c;数据变化自动更新UI&#xff0c;UI变化自动更新数据。 支持多设备&#xff0c;同时下载。 绑定单变量 在WPF (Windows Presentation Foundation) 中&#xff0c;您可以使用数据绑定来将变量绑定到界面元素。这允许您在界面上显示变量的值&#xff0c;…

CYEZ 模拟赛 7

A 弹珠 妙妙题。 先每个组分一个小球。等价于 n − k n-k n−k 拆分为任意个 [ 1 , k ] [1,k] [1,k] 的数的方案数。 本质是根据面积的转换&#xff0c;直观解释&#xff1a; 完全背包即可。代码。 B C 总结