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的广告条款,然后点击…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
