【C++】vector详解,模拟实现

目录

1. vector的介绍

2. vector的使用

2.1 构造函数

2.2 遍历方式

2.3 reserve与resize

2.4 shrink_to_fit 

2.5 insert,erase,find

3. vector模拟实现

3.1 初始结构

3.2 析构函数 

3.3 获取容量和元素个数

3.4 扩容reserve

3.5 resize改变有效个数并赋值val

3.6 方括号访问operator[]

3.7 迭代器

3.8 insert在pos前面插入

3.9 尾插push_back

3.10 erase删除pos位置的值

3.11 拷贝构造

3.12 赋值重载

3.13 用迭代器区间构造

3.14 用n个val构造


1. vector的介绍

vector是模板实现的。

Vectors are sequence containers representing arrays that can change in size.

 

2. vector的使用

使用上分几大部分:默认成员函数,迭代器,容量相关,访问相关,修改。

2.1 构造函数

void test1()
{//无参vector<int> v1;//有参vector<int> v2(10); //val的缺省值是0。vector<int> v3(10, 1);//迭代器vector<int> v4(v3.begin(), v3.end());//拷贝构造vector<int> v5(v4);
}

2.2 遍历方式

1. 下标加[ ],2. 迭代器,3. 范围for。

void test2()
{vector<int> v(10, 5);//下标+[]for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;//迭代器vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";it++;}cout << endl;//范围forfor (auto e : v){cout << e << " ";}cout << endl;
}

2.3 reserve与resize

reserve改变容量。

预先开空间就用reserve,容量改变,有效个数不变。


 

resize改变有效个数。


【区别】


【扩容机制】

vs:1.5倍扩容,g++:2倍扩容

2.4 shrink_to_fit 

缩容:将容量缩到和有效个数一样。

一般是异地缩容。

2.5 insert,erase,find

(1)在pos位置的元素前面插入val。

(2)在pos位置的元素前面插入n个val。

(3)在pos位置的元素前面插入一段迭代器区间。

注意:传入的是迭代器。


找到pos的位置需要借助find,find在算法库里,容器通用。

find传的迭代器区间都是左闭右开,没找到就返回last。


 删除某个位置或一段区间。

 


【结合用法】

void test3()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);for (auto e : v){cout << e << " ";}cout << endl;//头插v.insert(v.begin(), 9);for (auto e : v){cout << e << " ";}cout << endl;//在3前面插入6vector<int>::iterator it1 = find(v.begin(), v.end(), 3);if (it1 != v.end()){v.insert(it1, 6);}for (auto e : v){cout << e << " ";}cout << endl;//把6删除auto it2 = find(v.begin(), v.end(), 6);if (it2 != v.end()){v.erase(it2);}for (auto e : v){cout << e << " ";}cout << endl;
}

vector官方文档:vector - C++ Reference (cplusplus.com) 

 

3. vector模拟实现

3.1 初始结构

_start指向元素开始位置,_finish指向最后一个元素的下一个位置,_end指向最大容量的下一个位置。

namespace lyh
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;//无参构造vector(){}private:iterator _begin = nullptr;  //元素开始位置。iterator _end = nullptr;    //元素末尾的下一个位置。iterator _capacity = nullptr;    //最大容量的下一个位置。};
}

3.2 析构函数 

释放空间,指针置空。

        ~vector(){delete[] _begin;_begin = nullptr;_end = nullptr;_capacity = nullptr;}

3.3 获取容量和元素个数

利用指针相减。

		size_t size() const{return _end - _begin;}size_t capacity() const{return _capacity - _begin;}

3.4 扩容reserve

 n小于容量不用管,n大于容量才扩容。

新开一个大空间,拷贝数据,释放原空间,更新成员变量的指向。

memcpy是浅拷贝,这里用赋值重载才能完成深拷贝,内置类型就浅拷贝,自定义类型就调用自己的赋值重载。

		void reserve(size_t n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];//原空间有数据才需要拷贝。if (_begin){for (size_t i = 0; i < sz; i++){tmp[i] = _begin[i];}//释放原空间。delete[] _begin;}//更新成员指向。_begin = tmp;_end = tmp + sz;_capacity = tmp + n;}}

3.5 resize改变有效个数并赋值val

改变有效个数有三种情况。

小于原先size就缩小。

大于size就交给reserve判断要不要扩容,然后不断尾插直到n。

		void resize(size_t n, const T& val = T()){if (n <= size()){_end = _start + n;}else{reserve(n);while (_end < _begin + n){*_end = val;++_end;}}}

3.6 方括号访问operator[]

需要断言传入的下标是否合法,返回下标对应的元素的别名。可以提供const版本,可以访问但不能修改。

		T& operator[](size_t pos){assert(pos < size());return _begin[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _begin[pos];}

3.7 迭代器

begin指向第一个位置,end指向最后一个位置的下一个。可以提供const版本。

		iterator begin(){return _begin;}iterator end(){return _end;}const_iterator begin() const{return _begin;}const_iterator end() const{return _end;}

3.8 insert在pos前面插入

先断言pos在合法范围,再判断是否需要扩容,然后pos位置开始往后挪给pos腾出空间插入。

扩容是异地扩容除了更新原本的成员变量指向还需更新pos的指向,不然pos会变成野指针也就是迭代器失效。

		void insert(iterator pos, const T& val){assert(pos >= _begin && pos <= _end);if (_end == _capacity){size_t len = pos - _begin;reserve(capacity() == 0 ? 4 : capacity() * 2);pos = _begin + len;}iterator key = _end;while (key > pos){_start[key] = _start[key - 1];--key}*key = val;++_end;}

3.9 尾插push_back

复用insert

		void push_back(const T& val){insert(end(), val);}

3.10 erase删除pos位置的值

先断言pos是否合法,然后将pos之后的位置往前移。

erase之后认为迭代器失效,不能访问。

 ​

返回的迭代器指向原本删除元素的下一个元素。

An iterator pointing to the new location of the element that followed the last element erased by the function call.

		iterator erase(iterator pos){assert(pos >= _begin && pos < _end);iterator key = pos + 1;while (key < _end){*(key-1) = *key;++key;}--_end;return pos;}

3.11 拷贝构造

先开一个和v一样大的空间,再把v的元素拷贝过来(遍历尾插)。

		vector(const vector<T>& v){reserve(v.capacity());for (auto& e : v){push_back(e);}}

3.12 赋值重载

假设v3 = v1,将v1传值拷贝构造给tmp,v3和tmp交换。先拷贝构造给了形参再和形参交换。

		void swap(vector<T>& tmp){std::swap(_begin, tmp._begin);std::swap(_end, tmp._end);std::swap(_capacity, tmp._capacity);}vector<T>& operator=(vector<T> tmp){swap(tmp);return *this;}

3.13 用迭代器区间构造

当begin不等于end就不断尾插。

		vector(InputIterator begin, InputIterator end){while (begin != end){push_back(*begin);++begin;}}

3.14 用n个val构造

复用用resize。

		vector(size_t n, const T& val = T()){resize(n, val);}

Vector/Vector · 林宇恒/code-cpp - 码云 - 开源中国 (gitee.com) 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

方法引用(Java)

把已经有的方法拿过来用&#xff0c;当做函数式接口中抽象方法的方法体 1.引用处必须是函数式接口 2.被引用的方法必须已经存在 3.被引用的方法形参的返回值需要跟抽象方法保持一致 4.被引用方法的功能要满足当前需求 package function;import java.util.Arrays;public cl…

C++基础(3)——类和对象(中)

目录 1.类的默认成员函数 ​编辑 2. 构造函数 3. 析构函数 4. 拷⻉构造函数 5. 赋值运算符重载 5.1 运算符重载 5.2 赋值运算符重载 5.3 ⽇期类实现 6. 取地址运算符重载 6.1 const成员函数 6.2 取地址运算符重载 1.类的默认成员函数 简介&#xff1a;默认成员函数就…

day21JS-axios数据通信

1. 什么是axios axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端&#xff0c;简单的理解就是ajax的封装&#xff0c;只不过它是Promise的实现版本。 特性&#xff1a; 从浏览器中创建 XMLHttpRequests从 node.js 创建 http 请求支持 Promise API拦截请求和响应转…

论文笔记:交替单模态适应的多模态表征学习

整理了CVPR2024 Multimodal Representation Learning by Alternating Unimodal Adaptation&#xff09;论文的阅读笔记 背景MLA框架实验Q1 与之前的方法相比&#xff0c;MLA能否克服模态懒惰并提高多模态学习性能?Q2 MLA在面临模式缺失的挑战时表现如何?Q3 所有模块是否可以有…

ThreadX源码:Cortex-A7的tx_thread_irq_nesting_end(嵌套中断结束动作).s汇编代码分析

0 参考资料 Cortex M3权威指南(中文).pdf&#xff08;可以参考ARM指令集用法&#xff09; 1 前言 tx_thread_irq_nesting_end.S是用来实现Cortex-A7 IRQ嵌套中断的结束函数实现的汇编文件。 2 源码分析 源码如下&#xff1a; 1.#ifdef TX_ENABLE_FIQ_SUPPORT 2.DISABLE_INT…

【 ACM独立出版,见刊后1个月检索!!!】第二届通信网络与机器学习国际学术会议(CNML 2024,10月25-27)

第二届通信网络与机器学习国际学术会议&#xff08;CNML 2024&#xff09; The 2nd International Conference on Communication Networks and Machine Learning 官方信息 会议官网&#xff1a;www.cn-ml.org The 2nd International Conference on Communication Networks an…

jd 京东h5st 最新版 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我…

【Qt网络编程】Tcp多线程并发服务器和客户端通信

目录 一、编写思路 1、服务器 &#xff08;1&#xff09;总体思路widget.c&#xff08;主线程&#xff09; &#xff08;2&#xff09;详细流程widget.c&#xff08;主线程&#xff09; &#xff08;1&#xff09;总体思路chat_thread.c&#xff08;处理聊天逻辑线程&…

运筹说 第125期 | 存储论经典例题讲解1

通过前几期的学习&#xff0c;我们已经学会了存储论的基本概念、确定型存储模型、单周期的随机型存储模型、其他的随机型存储模型以及存储论应用研究中的一些问题。在实际工作中&#xff0c;我们能发现存储论在能源行业中有着许多应用&#xff0c;本期小编选择了其中一些确定型…

PyQt5-折叠面板效果

效果预览 实际效果中带有白色面板,看如下代码 实现代码 import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFrame, QLabel, QSizePolicy from PyQt5.QtCore import QPropertyAnimation, QEasingCurve, Qtclass CollapsiblePanel(QW…

C#:强大编程语言的多面魅力

C#&#xff1a;强大编程语言的多面魅力 一、C# 语言的特点与优势 &#xff08;一&#xff09;简洁的语法与精心设计 C# 在继承 C 和 C 的强大功能的同时&#xff0c;去掉了一些复杂特性&#xff0c;如宏和多重继承&#xff0c;使得语言更加简洁易懂。C# 是一种面向对象的语言…

openGauss之NestedLoop Join内表 Reuse

一. 前言 openGuass支持在做nestloop的时候&#xff0c;支持通过Materialize的方式将内表缓存到内存中&#xff0c;然后外表的数据内表数据进行碰撞的时候&#xff0c;如果内表已经缓存了数据&#xff0c;那么直接从缓存中直接读取内表的数据&#xff0c;从而实现内部数据Reuse…

基于SSM的在线家用电器销售系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSSMVueMySQL的在线家…

7--SpringBoot-后端开发、原理

配置优先级 SpringBoot 项目当中支持的三类配置文件&#xff1a; application.properties application.yml application.yaml 配置文件优先级排名&#xff08;从高到低&#xff09;&#xff1a; 1. properties配置文件 2. yml配置文件 3. yaml配置文件 在SpringBoot项目当…

MySQL 日志篇:Redo 相关线程

在 MySQL 中&#xff0c;用户线程开启事务更改数据时&#xff0c;系统内部会生成相应的 Redo Record。为了保证事务的持久性&#xff0c;这些 Redo Record 需要以 Redo Log 的形式在事务提交之前写入磁盘 (也称为“落盘”)。 为了提高事务的吞吐率 (单位时间内系统处理的事务数…

JavaSE - 面向对象编程01

01 什么是面向对象编程(oop) 答&#xff1a;就是只关心对象之间的交互&#xff0c;而并不关心任务是怎样具体完成的。例如把一个大象放进冰箱需要几步&#xff1f;如果是面向对象编程只会思考冰箱和大象之间的交互&#xff0c;那么给出的答案就是&#xff1a;把冰箱门打开&…

不可错过的AIGC浪潮:提升效率与竞争力的必备神器

随着人工智能生成内容&#xff08;AIGC&#xff09;技术的迅猛发展&#xff0c;它在提升工作效率和改善生活质量方面展示了巨大的潜力。对职场人来说&#xff0c;了解AIGC如何改变各个行业&#xff0c;并探讨其未来发展中的风险和机遇&#xff0c;将有助于他们更好地利用这项技…

三相可控整流电路 (三相半波,三相桥式)

目录 1. 三相半波整流电路 2. 三相桥式全控整流电路 三相可控整流电路利用三相交流电源&#xff0c;通过可控硅&#xff08;晶闸管&#xff09;将交流电整流为直流电。主要有两种常见类型&#xff1a;三相半波整流电路和三相桥式全控整流电路。 1. 三相半波整流电路 三相半波…

Java数据存储结构——二叉查找树

文章目录 22.1.2二叉查找树22.1.2.1 概述22.1.2.1二叉查找树添加节点22.1.2.2二叉查找树查找节点22.1.2.3 二叉树遍历22.1.2.4 二叉查找树的弊端 22.1.2二叉查找树 22.1.2.1 概述 二叉查找树,又称二叉排序树或者二叉搜索树 二叉查找树的特点&#xff1a; 每一个节点上最多有…

你的绩效是不是常年都是B

原创不易&#xff0c;求赞&#xff0c;求关注&#xff0c;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f;&#x1f64f; 目录 原创不易&#xff0c;求赞&#xff0c;求关注&#xff0c;&#x1f64f;&#x1f64f;&#x1f64…