【c++】vector的特性及使用

目录

一、vector的介绍及使用

1、vector迭代器的使用

2、vector的空间增长

3、vector的迭代器失效问题

二、vector的深度剖析与模拟实现


一、vector的介绍及使用

1、vector迭代器的使用

        vector的迭代器就是原生态指针。vector的迭代器使用方法与string的迭代器使用方法相同。

2、vector的空间增长

        (1)capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。

        (2)reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。

        (3)resize在开空间的同时还会进行初始化,影响size。

3、vector的迭代器失效问题

        迭代器的主要作用就是让算法不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装。比如:vector的迭代器就是原生态指针T*,因此迭代器失效实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。对于vector可能会导致其迭代器失效的操作有:

        (1)会引起底层空间改变的操作,都有可能导致迭代器失效。如:resize、reserve、insert、push_back等。

                以上操作都有可能导致vector扩容,即vector底层原来的旧空间被释放,而再打印时it还使用的释放之前的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放掉的空间,从而引起代码运行崩溃。如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可。

        (2)指定位置元素的删除操作---erase

                erase删除pos位置元素后,pos位置之后的元素会往前移动,没有导致底层空间的变化,理论上讲迭代器不应该失效,但是:如果pos刚好是最后一个元素,删除掉最后一个元素之后pos就变成了end的位置,而end位置是没有有效元素的,那么pos就会失效。因此,删除vector中任意位置上元素时,vs就会认为

        (3)Linux下,g++编译器对迭代器失效的检测并不是非常严格,处理也没有vs那么极端:

                a、扩容后,迭代器已经失效了,程序虽然可以运行,但是运行结果会发生变化。

                b、erase删除任意位置代码后,Linux下的迭代器不会失效,因为空间还是原来的空间,后续元素整体往前移动,it的位置还是有效的。

                c、erase删除的迭代器如果是最后一个元素,删除之后it已经超过end,此时迭代器失效,++it导致迭代器失效。

                总结:Linux中,迭代器失效后代码并不一定会崩溃,但是运行结果一定会改变,如果it不在begin和end的范围内,程序一定崩溃。

二、vector的深度剖析与模拟实现

        以vector的(push_back())尾插为例剖析其底层逻辑:

        vector的增删查改模拟实现:

//模拟实现vector类,并完成测试
namespace lbj
{template<class T>class vector{public:// Vector的迭代器是一个原生指针typedef T* iterator;typedef const T* const_iterator;//iteratoriterator begin(){return _start;}iterator end(){return _finish;}const_iterator cbegin() const{return _start;}const_iterator cend() const{return _finish;}// capacitysize_t size() const{return _finish - _start;}size_t capacity() const{return _endOfStorage - _start;}void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];size_t sz = size();if (_start){//memcpy(tmp, _start, sizeof(T) * size());for (size_t i = 0; i < size(); i++){tmp[i] = _start[i];}delete[] _start;}_start = tmp;_finish = _start + sz;_endOfStorage = _start + n;}}void resize(size_t n, const T& value = T()){if (n <= size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = value;_finish++;}}}//accessT& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}//modifyvoid push_back(const T& x){size_t sz = size();if (_finish == _endOfStorage){reserve(capacity() == 0 ? 5 : capacity() * 2);}*_finish = x;_finish++;}void pop_back(){--_finish;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endOfStorage, v._endOfStorage);}void insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);if (_finish == _endOfStorage){size_t len = pos - _start;reserve(capacity() == 0 ? 5 : capacity() * 2);pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;_finish++;}void erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;}// construct and destroyvector():_start(nullptr), _finish(nullptr), _endOfStorage(nullptr){}vector(int n, const T& value = T()):_start(nullptr), _finish(nullptr), _endOfStorage(nullptr){resize(n, value);}template<class InputIterator>   //类模板里边的模板函数vector(InputIterator first, InputIterator last)    //迭代器区间是左闭右开的形式{while (first != last){push_back(*first);first++;}}vector(vector<T>& v):_start(nullptr), _finish(nullptr), _endOfStorage(nullptr){reserve(v.capacity());for (auto num : v){push_back(num);}}vector<T>& operator= (vector<T> v)  //传值:会调用拷贝构造,生成临时对象,函数里边改变临时对象不会改变v的值{swap(v);return *this;}~vector(){delete[] _start;_start = nullptr;_finish = nullptr;_endOfStorage = nullptr;}private:iterator _start; // 指向数据块的开始iterator _finish; // 指向有效数据的尾iterator _endOfStorage; // 指向存储容量的尾};
}

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

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

相关文章

【CANopen】关于STM32中CanFestival的pdo应用

系列文章目录 文章目录 系列文章目录一、发送1、同步传输2、异步传输 二、接收 使用STM32F407单片机 pdo属于过程数据用来传输实时数据&#xff0c;即单向传输&#xff0c;无需接收节点回应。 一、发送 分为同步传输和异步传输。 1、同步传输 分为循环传输&#xff08;周期…

【12】ES6:模块化

一、JavaScript 模块化 JavaScript 模块化是一种组织和管理 JavaScript 代码的方法&#xff0c;它将代码分割为独立的模块&#xff0c;每个模块都有自己的作用域&#xff0c;并且可以导出和导入功能。模块化可以提高代码的可维护性、可重用性和可扩展性。 在JavaScript中&…

【vue/uniapp】使用 uni.chooseImage 和 uni.uploadFile 实现图片上传(包含样式,可以解决手机上无法上传的问题)

引入&#xff1a; 之前写过一篇关于 uview 1.x 版本上传照片 的文章&#xff0c;但是发现如果是在微信小程序的项目中嵌入 h5 的模块&#xff0c;这个 h5 的项目使用 u-upload 的话&#xff0c;图片上传功能在电脑上正常&#xff0c;但是在手机的小程序上测试就不会生效&#x…

漏洞复现--海康威视IP网络对讲广播系统远程命令执行

免责声明&#xff1a; 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…

职场革命:六款AI助手改写工作效率的故事

引言 在数字化时代&#xff0c;AI助手正快速成为职场的革命者。这些智能助手不仅仅是效率的提升者&#xff0c;它们更是创新的驱动力&#xff0c;重新定义了我们的工作方式。从自动化PPT创建到智能邮件优化&#xff0c;它们的影响深远且多元。本文将深入探讨六款不同领域的AI助…

三维模型数据的几何坐标变换的点云重建并行计算技术方法分析

三维模型数据的几何坐标变换的点云重建并行计算技术方法分析 倾斜摄影三维模型数据的几何坐标变换与点云重建并行计算技术的探讨主要涉及以下几个方面&#xff1a; 1、坐标系定义与转换&#xff1a;在进行坐标变换前&#xff0c;需要确定各个参考系的定义并实现坐标系之间的转…

卷积神经网络|制作自己的Dataset

在编写代码训练神经网络之前&#xff0c;导入数据是必不可少的。PyTorch提供了许多预加载的数据集&#xff08;如FashionMNIST&#xff09;&#xff0c;这些数据集 子类并实现特定于特定数据的函数。 它们可用于对模型进行原型设计和基准测试&#xff0c;加载这些数据集是十分…

阿里云服务器8080端口安全组开通图文教程

阿里云服务器8080端口开放在安全组中放行&#xff0c;Tomcat默认使用8080端口&#xff0c;8080端口也用于www代理服务&#xff0c;阿腾云atengyun.com以8080端口为例来详细说下阿里云服务器8080端口开启教程教程&#xff1a; 阿里云服务器8080端口开启教程 阿里云服务器8080端…

SkyWalking 快速入门

SkyWalking 是一个基于 Java 开发的分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容器&#xff08;Docker、K8s、Mesos&#xff09;架构而设计。 一、SkyWalking 简介 SkyWalking 是观察性分析平台和应用性能管理系统。 提供分布式追踪、服务网格…

输入输出流

1.输入输出流 输入/输出流类&#xff1a;iostream---------i input&#xff08;输入&#xff09; o output&#xff08;输出&#xff09; stream&#xff1a;流 iostream&#xff1a; istream类&#xff1a;输入流类-------------cin&#xff1a;输入流类的对象 ostream类…

使用Tensorboard可视化网络结构(基于pytorch)

前言 我们在搭建网络模型的时候&#xff0c;通常希望可以对自己搭建好的网络模型有一个比较好的直观感受&#xff0c;从而更好地了解网络模型的结构&#xff0c;Tensorboard工具的使用就给我们提供了方便的途径 Tensorboard概况 Tensorboard是由Google公司开源的一款可视化工…

【大模型+编程助手】国内编程助手安装与使用(CodeGeeX,Baidu Comate)

百度 Comate (可试用)&#xff1a;https://comate.baidu.com/ 清华CodeGeeX &#xff08;开源&#xff0c;暂时免费&#xff09;&#xff1a;https://codegeex.cn/ 华为&#xff1a;https://devcloud.cn-north-4.huaweicloud.com/codeartside/home?productsnap# 开发平台VScod…

贪吃蛇C语言实现(有源码)

前言 之前学了一点easyx图形库的使用&#xff0c;掌握一些基本用法后就用贪吃蛇来进行实战了&#xff0c;运行视频放在csdn视频那一栏了&#xff0c;之前的烟花也是。 1.头文件 #define _CRT_SECURE_NO_WARNINGS 1 #include<easyx.h> #include<conio.h> #includ…

【Vue2+3入门到实战】(21)认识Vue3、使用create-vue搭建Vue3项目、熟悉项目和关键文件

目录 一、认识Vue31. Vue2 选项式 API vs Vue3 组合式API2. Vue3的优势 二、 使用create-vue搭建Vue3项目1. 认识create-vue2. 使用create-vue创建项目 三、 熟悉项目和关键文件四、总结 一、认识Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {…

力扣题:高精度运算-1.2

力扣题-1.2 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;415. 字符串相加 解题思想&#xff1a;从后往前遍历两个字符串,然后进行相加即可 class Solution(object):def addStrings(self, num1, num2):""":type num1: str:type …

Navicat 技术干货 | 如何查看关系型数据库(MySQL、PostgreSQL、SQL Server、 Oracle)查询的运行时间

在数据库优化中&#xff0c;理解和监控查询运行时间是至关重要的。无论你是数据库管理员、开发人员或是参与性能调优的人员&#xff0c;知道如何查看查询运行时间能为你的数据库操作提供有价值的参考。本文中&#xff0c;我们将探索几款热门的关系数据库&#xff08;如 MySQL、…

ubuntu下快速安装使用docker

一、ubuntu下安装docker 1、命令行终端内直接输入docker 可以看到安装docker的命令提示 2、安装需要注意的几个点 (1)需要管理员权限 (2)更新软件源后再进行安装 命令行输入命令 sudo apt-get update #更新软件源 sudo apt install docker.io #安装docker 如图所示 二…

PostgreSQL荣获DB-Engines 2023年度数据库

数据库流行度排名网站 DB-Engines 2024 年 1 月 2 日发布文章宣称&#xff0c;PostgreSQL 荣获 2023 年度数据库管理系统称号。 PostgreSQL 在过去一年中获得了比其他 417 个产品更多的流行度增长&#xff0c;因此获得了 2023 年度 DBMS。 DB-Engines 通过计算每种数据库 2024 …

性能优化-OpenMP基础教程(一)

本文主要介绍OpenMP并行编程技术&#xff0c;编程模型、指令和函数的介绍、以及OpenMP实战的几个例子。希望给OpenMP并行编程者提供指导。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&am…

Mysql count统计去重的数据

不去重&#xff0c;是4 &#xff1a; SELECT COUNT(NAME) FROM test2 明显里面包含了2个 name 等于 mike的数据&#xff0c; 所以需要做去重 &#xff1a; 通过结合 count 函数和 DISTINCT 关键字 SELECT COUNT(DISTINCT NAME) FROM test2 好了就到这。