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的广告条款,然后点击…...

BFS 解决拓扑排序 , 课程表 , 课程表 II , 火星词典
文章目录 拓扑排序简介1.有向无环图(DAG图)2.AOV网:顶点活动图3.拓扑排序4.实现拓扑排序 207. 课程表210. 课程表 IILCR 114. 火星词典 拓扑排序简介 1.有向无环图(DAG图) 像这样只能从一个点到另一个点有方向的图&a…...

web安全攻防渗透测试实战指南_web安全攻防渗透测试实战指南,零基础入门到精通,收藏这一篇就够了
1. Nmap的基本 Nmap ip 6 ip Nmap -A 开启操作系统识别和版本识别功能 – T(0-6档) 设置扫描的速度 一般设置T4 过快容易被发现 -v 显示信息的级别,-vv显示更详细的信息 192.168.1.1/24 扫描C段 192.168.11 -254 上 nmap -A -T4 -v -i…...

大模型如何赋能智慧城市新发展?
国家数据局近期发布的《数字中国发展报告(2023)》显示,我国数据要素市场化改革步伐进一步加快,数字经济规模持续壮大,数字技术应用场景不断拓展。这一成就的背后是数字技术广泛应用,数字技术不仅影响着老百…...

随记——机器学习
前言 本来有个500块钱的单子,用机器学习做一个不知道什么鸟的识别,正好有数据集,跑个小项目,过一下机器学习图像识别的流程,用很短的时间记录下来..... 一、数据预处理 将数据集分为训练集和测试集,直接…...

【在Linux世界中追寻伟大的One Piece】进程间通信
目录 1 -> 进程间通信介绍 1.1 -> 进程间通信目的 1.2 -> 进程间通信发展 1.3 -> 进程间通信分类 1.3.1 -> 管道 1.3.2 -> System V IPC 1.3.3 -> POSIX IPC 2 -> 管道 2.1 -> 什么是管道 2.2 -> 匿名管道 2.3 -> 实例代码 2.4 -…...

多路复用IO
一。进程处理多路IO请求 在没有多路复用IO之前,对于多路IO请求,一般只有阻塞与非阻塞IO两种方式 1.1 阻塞IO 需要结合多进程/多线程,每个进程/线程处理一路IO 缺点:客户端越多,需要创建的进程/线程越多,…...

C++ prime plus-7-編程練習
1, #include <iostream>// 函数声明 double harmonicMean(double x, double y);int main() {double x, y, result;while (true) {std::cout << "请输入两个数(其中一个为0时结束): ";std::cin >> x >> y;…...

计算1 / 1 - 1 / 2 + 1 / 3 - 1 / 4 + 1 / 5 …… + 1 / 99 - 1 / 100 的值,打印出结果
我们写这道题的时候需要俩变量接受,一个总数一个分母,我们发现分母变化是有规律的从1~100循环。 #include<stdio.h> int main() {int i 0;int tag 1;double sum 0.0;for (i 1; i < 101; i){if (i % 2 0){sum sum - 1.0 / i;}else{sum s…...

Linux本地服务器搭建开源监控服务Uptime Kuma与远程监控实战教程
文章目录 前言**主要功能**一、前期准备本教程环境为:Centos7,可以跑Docker的系统都可以使用本教程安装。本教程使用Docker部署服务,如何安装Docker详见: 二、Docker部署Uptime Kuma三、实现公网查看网站监控四、使用固定公网地址…...

JS 历史简介
目录 1. JS 历史简介 2. JS 技术特征 1. JS 历史简介 举例:在提交用户的注册信息的时候,为避免注册出现错误后重新填写信息,可以在写完一栏信息后进行校验,并提示是否出现错误,这样会大大提高用户提交的成功率&…...