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

【C++】vector问题解决(非法的间接寻址,迭代器失效 , memcpy拷贝问题)

在这里插入图片描述
送给大家一句话:

世界在旋转,我们跌跌撞撞前进,这就够了 —— 阿贝尔 加缪

vector问题解决

  • 1 前言
  • 2 迭代器区间拷贝
  • 3 迭代器失效问题
  • 4 memcpy拷贝问题

1 前言

我们之前实现了手搓vector,但是当时依然有些问题没有解决:

  1. 迭代器区间拷贝(非法的间接寻址问题)
  2. 迭代器失效问题
  3. 使用memcpy拷贝问题

接下来,我们一点一点来解决这些问题!!!

2 迭代器区间拷贝

来看这个这个构造函数:

		template<class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}

这个是对迭代器区间进行的构造函数,思路很简单,把迭代器区间的数据依次尾插就可以了(这里之所以另外使用一个新的模版,而不是使用vector类的模版,是为了兼容更多的数据类型)。这样就可以通过一个现有的类型来构造容器。
但是出乎意料的是出现了一个问题: C2100 非法的间接寻址 (编译层面的问题) 。非法的间接寻址的造成原因有很多:

  1. 空指针引I用:当一个指针没有被初始化或者为NULL时,对它进行间接寻址操作会导致非法访问
  2. 野指针引用:当一个指针超出了它所指向的内存范围,或者已经被释放但仍然被引用时,进行间接寻址操作也会导致非法访问。
  3. 类型不匹配:如果试图将指针转换为不兼容的类型进行间接寻址,也会导致非法访问。

我们分析一下我们遇到的问题是那种问题?空指针引用吗?不可能!野指针引用吗?也不可能!!! 那么真相只有一个:我们遇到了类型不匹配的问题,那这是来自哪里的呢???,经过我的排除法(注释不同的代码块来进行查找),得到了结果

vector<int> v1(5,6);

这一行代码是我们出错的根源,为什么这个构造没有去使用vector(size_t n,T val = T()),而是使用我们的vector(InputIterator first, InputIterator last),因为第二个函数与(5,6)的类型更匹配,编译器会寻找最合适的函数。

解决方法也是十分暴力:多枚举几个 构造函数:

vector(size_t n,T val = T())
vector(int n,T val = T());
vector(long long n,T val = T());

这样就会优先匹配vector(int n,T val = T());了,我们的问题也就解决了。

3 迭代器失效问题

这个问题主要出现在我们的插入操作(insert)和删除操作(erase)。来看:

void vector_test7() {vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);v1.push_back(7);vector<int>::iterator it = v1.begin() + 3;// 4cout << *it << endl;v1.insert(3, 40);cout << *it << endl;
}

这个执行的结果是:
在这里插入图片描述
迭代器的指向发生了改变,我们实现的迭代器的底层是指针,我们插入之后指针位置不变,而数组元素改变,自然会产生不一样的结果。这个问题看起来不严重,那我们再来看:

void vector_test7() {vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);v1.push_back(7);v1.push_back(8);vector<int>::iterator it = v1.begin() + 3;// 4cout << *it << endl;v1.insert(3, 40);cout << *it << endl;
}

在这里插入图片描述
为什么这里出现了乱码???我们代码和之前的区别是什么???一个进行了扩容,一个没进行扩容。扩容之后vector的_start发生了改变,自然我们的指针也失去了对应作用。 迭代器就失效了,这个解决办法也很简单,就是插入之后不要使用之前的迭代器!!!一定要对迭代器进行更新。

再来看erase中的问题:

void vector_test7() {vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);//v1.push_back(6);//v1.push_back(7);//v1.push_back(8);vector<int>::iterator it = v1.begin();//删除偶数while (it != v1.end()){if (*it % 2 == 0){v1.erase(it);}++it;}print_vector(v1);
}

这样运行起来是没有问题的,那么再来看:

void vector_test7() {vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(4);v1.push_back(5);//v1.push_back(6);//v1.push_back(7);//v1.push_back(8);vector<int>::iterator it = v1.begin();//删除偶数while (it != v1.end()){if (*it % 2 == 0){v1.erase(it);}++it;}print_vector(v1);
}

现在出现了:
在这里插入图片描述
这个问题,问题的来源也很简单,我们迭代器在删除之后没有改变位置,但是_start的元素发生了改变,也就是相当于 it 向后移动了两次,为了避免这个情况我们可以:

	while (it != v1.end()){if (*it % 2 == 0){v1.erase(it);}else{++it;}}

这样就可以了:
在这里插入图片描述
需要注意的一点是,我们的操作是以g++标准来进行的(如果删除会进行缩容,也会出现错误,迭代器就不能进行++了),所以 在VS环境下,vector 容器在erase 之后的迭代器是严格不能使用的,使用就会报错,因为VS迭代器的底层不是原生指针,判断有所不同。
迭代器失效解决方案总结
1. 删除插入之后更新对应迭代器!(erase删除后会返回新的迭代器 ,按规则进行迭代就可以了 it = v1.erase(it)
2. 插入删除之后不使用迭代器

4 memcpy拷贝问题

我们创建一个string类的容器,来看看能不能正常运行:

void vector_test8() {vector<string> v1;v1.push_back("11111");v1.push_back("22222");v1.push_back("33333");v1.push_back("44444");v1.push_back("55555");print_vector(v1);
}

来看效果:
在这里插入图片描述程序直接崩掉了,经过我们的调试,我们能打印出来正确的数据,但是走到程序最后的时候出现了错误,那么应该就是析构函数的问题了!
来画图分析一波:

  1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
  2. 如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝
    在这里插入图片描述

结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃

那么怎么解决呢???非常简单:

		//扩容void reserve(size_t newcapacity) {//记录位置size_t n = _finish - _start;T* tmp = new T[newcapacity];//拷贝//memcpy(tmp, _start, size() * sizeof(T));for (size_t i = 0; i < size(); i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + n;_end = _start + newcapacity;}

不使用memcpy函数不就可以了,然后我们使用简单粗暴的赋值拷贝,这样就不会发生浅拷贝问题了!!!

相关文章:

【C++】vector问题解决(非法的间接寻址,迭代器失效 , memcpy拷贝问题)

送给大家一句话&#xff1a; 世界在旋转&#xff0c;我们跌跌撞撞前进&#xff0c;这就够了 —— 阿贝尔 加缪 vector问题解决 1 前言2 迭代器区间拷贝3 迭代器失效问题4 memcpy拷贝问题 1 前言 我们之前实现了手搓vector&#xff0c;但是当时依然有些问题没有解决&#xff…...

风控系统之普通规则条件,使用LiteFlow实现

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 提要 参考&#xff1a;智能风控筑基手册&#xff1a;全面了解风控决策引擎 前面有可配置输入参数的接…...

在一套Dockerfile中完成编译和运行环境部署

大纲 解释型语言编译环境解释环境编译型语言编译环境运行环境 方法编译环境安装系统安装编译依赖下载代码特殊处理&#xff08;可以忽略&#xff09;编译准备&#xff08;可以忽略&#xff09;编译打包依赖&#xff08;编译结果&#xff09; 运行环境安装操作系统安装运行时依赖…...

ubuntu系统里克隆github代码到本地,提示fatal: unable to connect to github.com的解决方案

打开命令行终端生成一个新的SSH密钥对。如果你还没有SSH密钥或者想创建一个新的&#xff0c;可以使用以下命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com"当系统提示你“Enter a file in which to save the key”&#xff0c;时&#xff0c;…...

常见docker使用命令

#搭建镜像 “”" sudo docker build -t es_refresh:V1.20230303 . “”" #启动容器 “”" docker run -d --namepara_classify -v /etc/localtime:/etc/localtime -v /data/chenhw/multi_label_classification:/edb2vec -p 8066:8066 --gpus ‘“device0”’…...

Ubuntu系统中设置中文输入法的教程

1、Ubuntu介绍&#xff1a; &#xff08;https://cn.ubuntu.com/&#xff09; &#xff08;Ubuntu | 全球领先的用于个人电脑、平板及手机的操作系统&#xff09; Ubuntu是一款基于Debian的开源Linux操作系统&#xff0c;由英国Canonical公司赞助支持的全球性社区共同开发。U…...

练习14 Web [极客大挑战 2019]Upload

phtml格式绕过&#xff0c;burp修改content-type绕过&#xff0c;常见的文件上传存放目录名 题目就叫upload&#xff0c;打开靶机 直接上传一个图片格式的一句话木马&#xff0c;返回如下&#xff1a; 提交练习5和9中的两种可以执行图片格式php代码的文件&#xff0c;修改con…...

3.6k star, 免费开源跨平台的数据库管理工具 dbgate

3.6k star, 免费开源跨平台的数据库管理工具 dbgate 分类 开源分享 项目名: dbgate -- 免费开源跨平台的数据库管理工具 Github 开源地址&#xff1a; GitHub - dbgate/dbgate: Database manager for MySQL, PostgreSQL, SQL Server, MongoDB, SQLite and others. Runs under…...

2024.3.2力扣每日一题——受限条件下可到达节点的数目

2024.3.2 题目来源我的题解方法一 深度优先搜索方法二 并查集 题目来源 力扣每日一题&#xff1b;题序&#xff1a;2368 我的题解 方法一 深度优先搜索 使用深度优先搜索实现&#xff0c;在搜索过程中根据restricted进行截停。 时间复杂度&#xff1a;O(n) 空间复杂度&#…...

在云端遇见雨云:一位服务器寻觅者的指南

引言&#xff1a;寻觅一座云端归宿 当我踏入数字世界的边缘&#xff0c;带着对网络的探索与期待&#xff0c;我迫切需要一座安全可靠的数字栖息地。云计算技术正如一场魔法般的变革&#xff0c;而在这片广袤的云端中&#xff0c;雨云就像是一位友善的向导&#xff0c;引领我穿越…...

Pygame基础10-物理模拟

PyMunk PyMunk是一个模拟物理的库。 注意&#xff0c;PyMunk只是进行物理模拟&#xff0c;不包含可视化的功能。如果需要可视化&#xff0c;可使用pygame等库。 可用pip安装pymunk pip install pymunk pymunk中的概念&#xff1a; space&#xff1a; 物理空间。 包含gravity 模…...

蓝桥杯 --- 日期问题模板

目录 1.如何判断闰年 2.如何遍历当前年份的每一天 3.如果想要输出某一年某一天到某一年某一天之间一共有多少天。 4.精确到具体周几到周几的问题分析 5.如何直接通过一层for循环枚举年月日 习题&#xff1a; 蓝桥杯竞赛特别喜欢考日期问题&#xff0c;今天给大家分享一下…...

Java 处理Mysql获取树形的数据

Mysql数据&#xff1a; 代码如下&#xff1a; Entity&#xff1a; Data Accessors(chain true) public class Region {private BigInteger id;//名称private String name;//父idprivate BigInteger parentId;private List<Region> children;private Integer createTim…...

前端三剑客 —— CSS ( 坐标问题 、定位问题和图片居中 )

前期内容回顾&#xff1a; 1.常见样式 text-shadow x轴 y轴 阴影的模糊程度 阴影的颜色 box-shadow border-radio 实现圆角 margin 内边距 padding 外边距 background 2.特殊样式 媒体查询&#xff1a;media 自定义字体&#xff1a;font-face { font-family:自定义名称&#…...

向量数据库 | AI时代的航道灯塔

向量数据库 | AI时代的航道灯塔 什么是向量检索服务拍照搜商品 你使用过向量数据库吗&#xff1f;使用体验&#xff1f;为什么向量数据库能借由大模型引起众多关注向量数据库在当前AI热潮中是昙花一现&#xff0c;还是未来AI时代的航道灯塔&#xff1f; 今天的话题主要是讨论向…...

Linux中的conntrack命令深入解析

在Linux网络管理和监控领域&#xff0c;conntrack命令是一个强大的工具&#xff0c;它提供了对netfilter连接跟踪系统的直接访问&#x1f50d;。这篇文章将深入探讨conntrack的由来、底层原理、参数意义&#xff0c;以及其常见用法&#xff0c;并对返回结果的每个字段进行详细解…...

反截屏控制技术如何防止信息通过手机拍照泄漏?

反截屏控制技术为企业数据安全提供了重要的防护措施。通过以下几点&#xff0c;有效阻止了信息通过拍照等方式的泄漏&#xff1a; 反截屏控制开启&#xff0c;用户启动截屏操作时&#xff0c;允许非涉密内容截屏操作&#xff0c;但所有涉密内容窗口会自动隐藏&#xff0c;防止涉…...

0.k8s简介

目录 k8s是什么 k8s不是什么 云原生 微服务 整体式架构与微服务架构 微服务的特性 微服务的优势 k8s是什么 Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快…...

VScode 集成终端设置默认打开当前文件夹 mac系统

一.快捷键设置 搜索 openInIntegratedTerminal 如图&#xff1a; 二.设置cmd 默认打开位置 点击设置 搜索 ntegrated:cwd 如下图&#xff1a; 三.查看ip 快捷指令&#xff1a; ipconfig getifaddr en0...

HDLbits 刷题 -- Alwaysblock2

学习&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*)Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...

密码学基础——SM4算法

博客主页&#xff1a;christine-rr-CSDN博客 ​​​​专栏主页&#xff1a;密码学 &#x1f4cc; 【今日更新】&#x1f4cc; 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...