vector类
一、STL库 vector
1.1 vector的介绍
vector英文意思为向量:向量是表示大小可以改变的数组的序列容器。
指向其元素的常规指针上的偏移量来访问其元素,并且与数组中的效率一样高。但与数组不同,它们的大小可以动态变化,其存储由容器自动处理。
总之,vector就是一个可以动态开辟空间的任意类型的容器,可以看成一个自定义类型动态序列,支持随机访问,尾插尾删效率高。
可以通过看文档来了解:vector - C++ Reference (cplusplus.com)
这里包含allocator的可以看成无参,以后再说。
1.2vector的使用
1.2.1构造函数constructor
选择几种着重介绍
vector()(重点)
vector(size_type n, const value_type& val =value_type())
vector (const vector& x); (重点)
vector (InputIterator first, InputIterator last);
value_type是模版T
size_type是由 typedef 而来本质是size_t
value_type()不是一个函数,而是类似于构造,不过是对于内置类型的构造
一般它的值是0
几乎所有值的是0,包括字符对应的Ascll也是0
但是这种构造是不适合指针的;
补充完知识,现在开始看vector的构造
值得注意的是vector的底层,它是有三个指针构成的
分别对应指向动态开辟空间的三个指针:这个在后面的模拟实现会说到
还有一点,使用迭代器构造时,可以跨容器进行构造
1.2.2迭代器
迭代器的作用还是为了遍历
1.2.3vector 空间函数
size_type size()const; 返回大小
size_type capacity()const;返回容量
bool empty()const;判空
void resize(size_type n, value_type val=value_type());以某值初始化改容
void reserve(size_t n);扩容
就看着几个够用了
前三个不同看了,很简单
void resize(size_type n, value_type val=value_type());
如果,n小于目前的size,那么就会保留前n个元素。移除剩下不要的元素
如果n大于size小于capacity的话,就会以某一个值扩充元素直到n==size
如果大于capacity的话就会扩容。(重新分配空间)
不举例了,已经很清楚了
void reserve(size_t n);
其实就是扩容,n大于capacity时扩容小于等于不影响。并且reserve不改变vector的元素
1.2.4vector的增删查改
增删查改都会影响到容量,大小,如果大小为0还要删就会报错
如果容量不够时,就需要扩容
举例吧!
int main()
{vector<int>vec(1, 5);cout << "扩容前" << vec.capacity() << endl;vec.push_back(1);vec.push_back(1);vec.push_back(1); vec.push_back(1);printf("打印元素:");for (auto e : vec){cout<<e<< " ";}cout <<endl<<"扩容后" << vec.capacity() << endl;vec.pop_back(); vec.pop_back(); vec.pop_back(); vec.pop_back();for (auto e : vec) { cout << e << " "; }return 0;
}
提醒:不同平台扩容机制不同,但是底层相同
insert与string有所不同,这里是通过迭代器来insert的,最后一个函数是通过迭代器查找位置然后使用一个迭代器区间进行插入,这里支持跨容器。
vector<int>vec(10, 5);
vector<int>::iterator it = vec.begin();
vec.insert(it, 1);
for (auto& e : vec) { cout << e << " "; }
cout << endl;
//这里迭代器的位置发生了改变,所以要让它重回位置
//这里也叫做迭代器失效
it = vec.begin();
vec.insert(it, 5, 10);
for (auto& e : vec) { cout << e << " "; }
erase的使用也很简单
删除某个位置数据,删除某个迭代器区间位置
int main()
{vector<int>vec{1, 2, 3, 4, 5, 67, 8, 9, 10, 11, 12};for (auto& e : vec) { cout << e << " "; }cout << endl;auto it = vec.begin();vec.erase(it);for (auto& e : vec) { cout << e << " "; }cout << endl;//防止迭代器失效it = vec.begin();vec.erase(it,it+3);//左闭右开for (auto& e : vec) { cout << e << " "; }cout << endl;return 0;
}
当然,也可以接受erase的返回值,此时erase返回的就是删除元素位置的下一个元素的迭代器
find在vector中只有全局的函数
看到它的声明,就已经理解了含义了!
使用迭代器确定区间,查找某一个元素
成功返回该元素的迭代器,失败返回最后一个迭代器
举例很简单
int main()
{
vector<int>vec{ 1,23,4,6,6 };
vector<int>::iterator it=find(vec.begin(), vec.end(), 23);
if (it != vec.end())
{
cout << "找到了" << endl;
}
else
cout << "没有找到" << endl;
return 0;
}
好吧,就是这么用。
这个就是支持随机访问吧!!
很简单的。
int main()
{
vector<int>vec{ 1,2,3,4,5,6,7,8,9,10 };
cout<<vec[0]<<endl;
cout<<vec[5]<<endl;
cout<<vec[9]<<endl;return 0;
}
1.2.5vector补充
vector在示例化的时候不仅可以使用内置类型实例化,还可以使用容器实例化。
vector<string> a;
vector<list<int>>b;
vector<vector<int>>c;
在进行初始化时,还有一些方式
vector<int>vec10{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int>vec1; vector<int>vec2; vector<int>vec3; vector<int>vec4; vector<int>vec5;
vector<vector<int>>vec7{ vector<int>{1,2,3,4,5},vector<int>{1,2,3,4}};
vector<vector<int>>vec6{ vec1,vec2,vec3,vec4 };
vector<vector<int>>vec8{ {1,2,3},{1,23,5} };//这些都是为了最后一种的简化
//主要的原理还是隐式类型转换
二、vector的模拟实现
2.1代码实现
#pragma once
#include<iostream>
#include<assert.h>
namespace practice {
template<class T>
class vector {
public:typedef T* iterator;typedef const T* const_iterator;iterator begin(){return _start;}const_iterator begin()const{return _start;}iterator end(){return _finish;}const_iterator end() const{return _finish;}size_t size() const{return _finish - _start;}size_t capacity() const{return _end_of_storage - _start;}vector():_start(nullptr),_finish(nullptr), _end_of_storage(nullptr){}vector(size_t n,const T& val=T()){resize(n,val);}~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}//vector(const vector<T>&vec){reserve(vec.capacity());for (int i = 0; i < vec.size(); ++i){_start[i] = vec[i];}}void reserve(size_t n){if (n >capacity()){T* temp = new T[n];if (_start != nullptr){size_t oldsize = size();for (size_t i = 0; i < size(); ++i){temp[i] = _start[i];}delete[] _start;_start = temp;_finish = _start + oldsize;_end_of_storage = _start + n;}else{_start = temp;_finish = _start;_end_of_storage = _start + n;}}}void resize(size_t n,const T& val=T()){if (n <=size()){_finish = _finish - (size() - n); return;}if (n > capacity()){reserve(capacity() == 0 ? 4 : 2 * capacity());}size_t x = n - size();for (int i = 0; i < x; ++i){*_finish++ = val;}}iterator insert(iterator pos ,const T val ){assert(pos >= begin());assert(pos <=end());size_t xpos = pos - begin();if (_finish == _end_of_storage){reserve(capacity()==0?4:2 * capacity());pos = _start + xpos;}iterator it = end();while (it != pos){*(it) = *(it-1);--it;}*pos = val;return pos;}iterator erase(iterator pos){assert(pos >= begin());assert(pos < end());iterator it = pos;while (it != end()){*(it) = *(it +1);it++;}return pos;}T& front(){assert(size() > 0);return _start[0];}const T& front()const{assert(size() > 0);return _start[0];}T& back(){assert(size() > 0);return _start[size() - 1];}const T& back() const{assert(size() > 0);return _start[size() - 1];}bool empty() const{return size() == 0;}void push_back(const T& val){if (_end_of_storage == _finish){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish++ = val;}void pop_back(){assert(size() > 0);_finish--;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}vector<T>& operator=(vector<T> v){swap(v);return *this;}T& operator[](size_t i){assert(i < size());return _start[i];}const T& operator[](size_t i) const{assert(i < size());return _start[i];}
private:T *_start;T *_finish;T *_end_of_storage;
};
template<typename container>
void print_container(const container& con)
{for (auto& e : con){std::cout << e <<" ";}std::cout << std::endl;
}
}
2.2 注意事项
1. vector类的迭代器,无需封装,就是模版类型指针。
2.在进行扩容时,会涉及到异地扩容,如果vector的模版类型是内置类型,使用memcpy没有错,但是如果是自定义类型就会发生内容丢失,因为删除旧空间时,就有可能把自定义类型指向的资源删除,但是memcpy不会深拷贝
3.在未实例化模版内找类型时,可能会报错,要加上typename,让编译器认为是类型
4.使用mecpy的拷贝问题,这是一个浅拷贝的问题。使用memcpy拷贝内置内型没有问题
但是使用它拷贝自定义类型时,是浅拷贝,会造成数据丢失。
相关文章:

vector类
一、STL库 vector 1.1 vector的介绍 vector英文意思为向量:向量是表示大小可以改变的数组的序列容器。 指向其元素的常规指针上的偏移量来访问其元素,并且与数组中的效率一样高。但与数组不同,它们的大小可以动态变化,其存储由容…...

python常见的魔术方法
什么是魔术方法 Python类的内置方法,各自有各自的特殊功能,被称之为魔术方法 常见的魔术方法有以下: __init__:构造方法 __str__:字符串方法 __lt__:小于、大于符号比较 __le__:小于等于、大于等于符合比较 __eq__:等于符合比较__init__ c…...

自动化测试常用函数:弹窗、等待、导航、上传与参数设置
目录 一、弹窗 1. 警告弹窗确认弹窗 2. 提示弹窗 二、等待 1. 强制等待 2. 隐式等待 3. 显示等待 三、浏览器导航 1. 打开网站 2. 浏览器的前进、后退、刷新 四、文件上传 五、浏览器参数设置 1. 设置无头模式 2. 页面加载策略 一、弹窗 弹窗是在页面是找不到任何…...

【必看】2024国赛选题分布情况分析及数模国赛答辩指南~答辩不走弯路
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 紧张刺激的数模国赛已经过去一段时间,各赛区的成绩发布也在陆续进…...

微服务注册中⼼1
1. 微服务的注册中⼼ 注册中⼼可以说是微服务架构中的”通讯录“ ,它记录了服务和服务地址的映射关系。在分布式架构中, 服务会注册到这⾥,当服务需要调⽤其它服务时,就这⾥找到服务的地址,进⾏调⽤。 1.1 注册中⼼的…...
我设置了路由器自动切换ip,这会让我的账号登录地址经常改变吗
是的,路由器设置自动切换IP可能会导致你的账号登录地址经常改变。 这是因为当路由器切换IP时,外部网络所看到的你的设备IP地址也会随之改变。对于很多跨境电商、社交媒体或者银行账户等需要较高安全性的系统来说,经常变动的IP地址可能会被视…...
Nginx 限流实战教程和技巧
Nginx限流是一种重要的技术手段,用于保护服务器资源,防止因过度请求而导致的服务不可用。以下是一个详细的Nginx限流教程,包括限流原理、常用模块和配置示例。 一、Nginx限流原理 Nginx限流主要基于两种算法:漏桶算法和令牌桶算…...

AlphaFold3 | 详解 AlphaFold3 的模型结构及其在不同类型的预测实验中的表现
Jumper 本文将介绍 24 年 5 月发布的 Alaphafold3,其以“使用 AlphaFold 3 进行生物分子相互作用的精确结构预测”为标题发表在《nature》上,通讯作者为 Jumper。 Jumper 具有物理、化学、生物和计算方面的丰富背景。Jumper 本科学的是物理和数学&#…...

公交IC卡收单管理系统 多处 SQL注入致RCE漏洞复现
0x01 产品简介 公交IC卡收单管理系统是城市公共交通领域中不可或缺的一部分,它通过集成先进的集成电路技术(IC卡)实现了乘客便捷的支付方式,并有效提高了公共交通运营效率。系统集成了发卡、充值、消费、数据采集、查询和注销等多个功能模块,为公交公司和乘客提供了全面、…...

淘客系统开发之卷轴模式系统源码功能分析
随着互联网技术的快速发展,电商行业不断创新,探索更加高效、有趣的用户参与机制。其中,卷轴模式作为一种新兴的商业模式,以其独特的积分兑换和任务系统,在淘客系统开发中得到了广泛应用。本文将从技术角度,…...
MoCo中的字典
在 MoCo(Momentum Contrast)中,字典(dictionary)是一个核心组件,用于存储负样本(negative samples)的特征表示(key)。这个字典的设计使得 MoCo 可以高效地利用…...

Xcode16 iOS18 编译问题适配
问题1:ADClient编译报错问题 报错信息 Undefined symbols for architecture arm64:"_OBJC_CLASS_$_ADClient", referenced from:in ViewController.o ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit co…...
加密解密的艺术:探索Java中的DES算法
目录 1. 引言 2. DES算法简介 3. Java中的DES实现 4. 代码解析 5. 安全性考量 1. 引言 在数字化时代,数据安全变得至关重要。无论是个人隐私还是企业机密,都需要强有力的保护措施。今天,我们将探讨一种经典的数据加密技术——DES&#…...

jQuery——层次选择器
1、层次选择器:查找子元素,后代元素,兄弟元素的选择器。 ancestor descendant:在给定的祖先元素下匹配所有的后代元素 parent > child:在给定的父元素下匹配所有的子元素 prev next:匹配所有紧接在…...

MySQL常见面试总结
MySQL基础 什么是关系型数据库? 顾名思义,关系型数据库(RDB,Relational Database)就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多&…...

记录一次学习--委派攻击学习
目录 为什么要使用委派 什么账号可以使用委派 非约束性委派 这里有一张图 利用 流程 约束性委派 这里有一张图 如何利用 条件 具体流程 为什么要使用委派 这个是因为可能A服务需要B服务的支持,但是A服务的权限不可以使用B服务。然后这时就可以让域用户将…...
前端列表数据太多导致页面卡顿就这么处理
前端列表数据太多页面卡顿就这么处理 实际场景什么是虚拟列表虚拟列表实现原理实战中虚拟列表的问题及相应解决方案 实际场景 首先看以下两个实际场景: 场景一:有一个数据列表,数据量非常大且每一个数据项都有几十列甚至更多,且后…...

机器学习_神经网络_深度学习
【神经网络——最易懂最清晰的一篇文章 - CSDN App】https://blog.csdn.net/illikang/article/details/82019945?type=blog&rId=82019945&refer=APP&source=weixin_45387165 参考以上资料,可对神经网络有初步了解。接下来可参考书籍等投身实际项目中使用。 书…...

MT6765/MT6762(R/D/M)/MT6761(MT8766)安卓核心板参数比较_MTK联发科4G智能模块
联发科Helio P35 MT6765安卓核心板 MediaTek Helio P35 MT6765是智能手机的主流ARM SoC,于2018年末推出。它在两个集群中集成了8个ARM Cortex-A53内核(big.LITTLE)。四个性能内核的频率高达2.3GHz。集成显卡为PowerVR GE8320,频率…...

TikTok五分钟开户快速步骤流程!
1、注册您的账户 首先,访问TikTok广告管理器的注册页面(https://ads.tiktok.com/i18n/signup/)以创建账户。您可以选择使用电子邮件或手机号码进行注册。输入您的电子邮件和密码后,您需要同意TikTok的广告条款,然后点击…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...