STL vector详解

STL vector详解

  • 1. 简介
  • 2. vector的内存机制
  • 3. vector 基类源码_Vector_base
    • 3.1. vector 基类成员变量
    • 3.2. vector 基类方法
    • 3.3. _Vector_base 总结
  • 4. vector类
    • 4.1. 方法

1. 简介

本文参考vector源码,主要介绍vector的设计思路,了解一些方法的实现原理,内存机制。

2. vector的内存机制

模板类vector是一种动态数组。在运行阶段可以设置vector对象的长度,可在末尾添加新数据,还可以在中间插入新数据。vector使用new和delete来管理内存,但这种工作是自动完成的,每次内存不够会自动开辟一段新的空间,自动开辟的空间大小是原空间大小的2倍,如果第一次开辟因为原来没有开辟空间就开辟1个字节的空间。

3. vector 基类源码_Vector_base

源码如下:

template <class _Tp, class _Alloc> 
class _Vector_base {
public:typedef _Alloc allocator_type;allocator_type get_allocator() const { return allocator_type(); }_Vector_base(const _Alloc&): _M_start(0), _M_finish(0), _M_end_of_storage(0) {}_Vector_base(size_t __n, const _Alloc&): _M_start(0), _M_finish(0), _M_end_of_storage(0) {_M_start = _M_allocate(__n);_M_finish = _M_start;_M_end_of_storage = _M_start + __n;}~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }protected:_Tp* _M_start;_Tp* _M_finish;_Tp* _M_end_of_storage;typedef simple_alloc<_Tp, _Alloc> _M_data_allocator;_Tp* _M_allocate(size_t __n){ return _M_data_allocator::allocate(__n); }void _M_deallocate(_Tp* __p, size_t __n) { _M_data_allocator::deallocate(__p, __n); }
};

3.1. vector 基类成员变量

  _Tp* _M_start;  //vector存储数据存储的首地址_Tp* _M_finish; //vector存储数据存储的尾地址+1 其实就是vector::end()返回的迭代器_Tp* _M_end_of_storage; //vector占用内存的尾地址

其实vector中只有三个指针成员因此sizeof一个vector对象的大小就是sizeof指针大小的三倍,32bit系统和64bit系统可能会有一些差别。64bit系统中vector占用内存空间为3*8=24字节。

3.2. vector 基类方法

构造函数

  _Vector_base(const _Alloc&)  // 指定一个空间配置器: _M_start(0), _M_finish(0), _M_end_of_storage(0) {}_Vector_base(size_t __n, const _Alloc&)  //指定vector 空间大小__n*sizeof(_Tp) 指定一个空间配置器: _M_start(0), _M_finish(0), _M_end_of_storage(0) {_M_start = _M_allocate(__n); //这行代码相当于开辟了n*sizeof(_Tp) (_Tp是vector中存储类型)这么大的空间_M_finish = _M_start; //没有成员时finish = start_M_end_of_storage = _M_start + __n; //vector占用内存的尾地址}
  allocator_type get_allocator() const { return allocator_type(); } //获取空间配置器类型_Tp* _M_allocate(size_t __n);  //开辟空间void _M_deallocate(_Tp* __p, size_t __n);  //释放空间

3.3. _Vector_base 总结

通过两个构造函数就可以知道,构造_Vector_base 时需要指定空间配置器同时也可以指定size,如果指定了size就会开辟sizesizeof(_Tp)这么大的空间,_M_start 指针指向这块空间的首地址,_M_finish 和_M_start 指向同一块地址(因为目前虽然开辟了空间但是并没有向vector中存入数据)。_M_start 指向的是vector中存入数据的首地址,_M_finish指向的是vector中存入数据的尾地址+1(其实就是vector::end()返回的迭代器),_M_end_of_storage就是vector内开辟空间的尾地址+1,也就是(vector::capacity()返回的值)
下图为_M_start ,_M_finish ,_M_end_of_storage指针在vector中所指向的内存位置示意图使用的是vector<int32_t>
下图vector中开辟了4
4个字节的空间(相当于调用vector<int32_t>::reserve(4)),并且向vector中插入了2个int32_t值1,2。
在这里插入图片描述

4. vector类

其实vector源码中_Vector_base 类的源码就可以展示出vector的设计思路也是精华部分,vector类中的方法主要提供给用户使用vector,因此vector那部分源码就不展示了感兴趣的可以自己去看看。
vector类中没有任何成员,继承了_Vector_base 类提供了一些公有的方法,下面主要说明下vector中的公有方法

4.1. 方法

首先了解下vector中typedef的部分类型

  typedef _Tp value_type;typedef value_type* pointer;typedef const value_type* const_pointer;typedef value_type* iterator;   //迭代器其实就是指针typedef const value_type* const_iterator;typedef value_type& reference;  //引用typedef const value_type& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;

vector的构造函数

  explicit vector(const allocator_type& __a = allocator_type())     //可以指定空间配置器,也可以使用默认的空间配置器: _Base(__a) {}vector(size_type __n, const _Tp& __value,const allocator_type& __a = allocator_type())     //可以指定vector成员个数和初始化成员的值: _Base(__n, __a){ _M_finish = uninitialized_fill_n(_M_start, __n, __value); }explicit vector(size_type __n)    //可以指定vector成员个数,指定个数同时就会开辟对应的空间sizeof(_Tp)*__n: _Base(__n, allocator_type()){ _M_finish = uninitialized_fill_n(_M_start, __n, _Tp()); }vector(const vector<_Tp, _Alloc>& __x)  //拷贝构造: _Base(__x.size(), __x.get_allocator()){ _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }vector(const _Tp* __first, const _Tp* __last,const allocator_type& __a = allocator_type())  //从迭代器的__first位置拷贝到迭代器__last位置: _Base(__last - __first, __a)   //相当于在基类里面创建了一个__last - __first这么大的空间{ _M_finish = uninitialized_copy(__first, __last, _M_start); }
函数描述
iterator begin()获取_M_start位置的迭代器也就是vector开辟内存的起始指针有个重载返回的是const 的_M_start位置的迭代器
const_iterator cbegin()返回的是一个const 的_M_start位置的迭代器
iterator end()获取_M_finish位置的迭代器也就是vector内尾成员后一个位置的指针,有个重载返回的是const 的_M_finish位置的迭代器
const_iterator cend()返回的是一个const 的_M_finish位置的迭代器
reverse_iterator rbegin()返回的是一个reverse_iterator内部存储_M_finish位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_finish位置前一个位置的内容返回值类似 * - - _M_finish
const_reverse_iterator crbegin()返回const_reverse_iterator
reverse_iterator rend()返回的是一个reverse_iterator内部存储_M_start位置的迭代器,但是里面实现很多重载操作符比如operator*()实际返回的是_M_start位置前一个位置的内容返回值类似 * - - _M_start
const_reverse_iterator crend()返回const_reverse_iterator
size_type size()返回的是_M_finish-_M_start也就是vector中实际存储的成员个数
size_type max_size()返回vector所能储存的最大的元素数目,容器所能容纳的最大元素数目,这是系统或者库所实施的限制。但是容器不一定保证能达到该大小,有可能在还未达到该大小的时候,就已经无法继续分配任何的空间了。
size_type capacity()返回容器的容量(开辟空间大小/sizeof(_Tp))比如vector<int32_t>如果返回的是10也就代表当前容量最多可以存储10个uint32_t也就是开辟了4*10这么大空间
bool empty()返回的是begin()==end() 也就是容器是否是空
reference operator[](size_type __n)返回的是一个*(begin()+__n)引用 还有个重载返回的是一个const 引用
void reserve(size_type __n)()设置vector容量为__n及如果当前容量小于__n则需要开辟到__n*sizeof(_Tp)(这么大就可以存储__n个_Tp类型的对象),如果当前容量大于__n则直接返回
void assign(size_type __n, const _Tp& __val)给vector填充__n个 值为__val 的数据
template < class _InputIterator>
void assign(_InputIterator __first, _InputIterator __last)
给vector重新填充数据从迭代器__first到迭代器__last,set的begin(),end()填入该函数可以将set的值赋值给vector
reference front()返回一个*begin()也就是返回vector中起始位置的引用
const_reference front()返回一个*begin()也就是返回vector中起始位置的const 引用
reference back()返回一个*(end()-1)也就是返回vector中末尾位置的引用
const_reference back()返回一个*(end()-1)也就是返回vector中末尾位置的const 引用
void push_back(const _Tp& __x)在vector末尾插入一个值,现在可以使用emplace_back代替,emplace_back效率更高少一次拷贝
void emplace_back(_Args&&… __args)在vector末尾插入一个值
template< typename _InputIterator>
void insert(iterator __position, _InputIterator __first, _InputIterator __last)
在指定位置插入从__first到__last之间的所有值并返回__first插入位置的迭代器
iterator insert(const_iterator __position, size_type __n, const value_type& __x)在指定位置插入n个值为__x的值并返回第一个插入位置的迭代器
iterator insert(const_iterator __position, initializer_list<value_type> __l)在指定位置插入一个C风格的数组并返回第一个插入位置的迭代器
iterator insert(const_iterator __position, const value_type& __x)在指定位置插入该值并返回该位置的迭代器
iterator emplace(const_iterator __pos, _Args&&… __args)在指定位置插入该值并返回该位置的迭代器
iterator erase(iterator __position)删除指定位置的值,返回的迭代器指向删除的值的下一个位置
void swap(vector& __x)当前vector和参数中的vector里面的值进行交换
void clear()清空vector

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

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

相关文章

20240506 深度学习高级技术点

1.基于BN层剪枝 基于Batch Normalization (BN)层进行剪枝是一种常用的模型压缩方法&#xff0c;特别是在卷积神经网络(CNNs)中。BN层在训练期间用于加速收敛和提高模型的泛化能力&#xff0c;而在剪枝过程中&#xff0c;BN层提供的统计信息&#xff08;特别是均值(mean)和方差…

HarmonyOS实战开发-如何通过BlendMode属性来实现挂件和图片的混合

介绍 本实例主要通过BlendMode属性来实现挂件和图片的混合&#xff0c;通过更改不同的混合参数&#xff0c;能够展示不同的混合效果。 效果图预览 使用说明&#xff1a; 1.进入页面&#xff0c;点击挂件区域&#xff0c;进行挂件和图片的混合&#xff0c;点击不同的挂件&…

Golang 开发实战day12 - Pointer

&#x1f3c6;个人专栏 &#x1f93a; leetcode &#x1f9d7; Leetcode Prime &#x1f3c7; Golang20天教程 &#x1f6b4;‍♂️ Java问题收集园地 &#x1f334; 成长感悟 欢迎大家观看&#xff0c;不执着于追求顶峰&#xff0c;只享受探索过程 Golang 开发实战day12 - 指针…

Python实验代码定时调起

Python代码实验调参需要等待1小时运行完成&#xff0c;自动将提前设置的5组参数&#xff08;每组参数有8个&#xff09;间隔1小时之后让Python代码再次自动依次调起运行其中的一组参数&#xff0c;每次跑完将实验结果写一个文件在本地存储通过邮件发送运行结果到指定QQ邮箱 im…

国家电网某地电力公司网络硬件综合监控运维项目

国家电网某地电力公司是国家电网有限公司的子公司&#xff0c;负责当地电网规划、建设、运营和供电服务&#xff0c;下属多家地市供电企业和检修公司、信息通信公司等业务支撑实施机构。 项目现状 随着公司信息化建设加速&#xff0c;其信息内网中存在大量物理服务器、存储设备…

Linux动态库与静态库解析

文章目录 一、引言二、C/C源文件的编译过程三、静态库1、静态库的定义和原理2、静态库的优缺点3、静态库的创建和使用a、创建静态库b、使用静态库 四、动态库1、动态库的定义和原理2、动态库的优缺点3、动态库的创建和使用示例a、创建动态库b、使用动态库 五、动静态库的比较 一…

Pytorch学习笔记——神经网络基本框架

一、神经网络是什么 神经网络在人工智能和深度学习的领域&#xff0c;一般称为人工神经网络&#xff0c;即ANN(Artificial Neural Network)&#xff0c;是一种模仿人脑神经系统工作方式的计算模型。被广泛应用于人工智能、自动控制、机器人、统计学等领域的信息处理中。 二、…

套管外径测量仪 多尺寸型号 规格全可定制

套管&#xff08;bushing&#xff09;是一种将带电导体引入电气设备或穿过墙壁的一种绝缘装置。前者称为电器套管&#xff0c;后者称为穿墙套管。套管通常用在建筑地下室&#xff0c;是用来保护管道或者方便管道安装的铁圈。套管的分类有刚性套管、柔性防水套管、钢管套管及铁皮…

【快速幂取模】

求 a 的 b 次方对 p 取模的值&#xff0c;其中 1≤a,b,p≤109 输入 三个用空格隔开的整数a,b和p。 输出 一个整数&#xff0c;表示ab mod p的值。 样例输入 Copy 2 3 9样例输出 Copy 8 思路&#xff1a; 这里借鉴一下大佬的用例&#xff1a; #include<bits/stdc.h&…

idea提示 CreateProcess error=206, 文件名或扩展名太长有哪些具体的解决方法

背景&#xff1a; 项目启动后提示CreateProcess error206&#xff0c;通常我本地是将shorten command line改成如下就可以解决&#xff0c;但是今天遇到一个&#xff0c;无论这里怎么设置都是启动提示扩展名太长&#xff0c;经过一番处理问题终于解决&#xff0c;特此记录一下。…

面试笔记——垃圾回收

对象被垃圾回收的时机 垃圾回收主要面向的是堆中的对象。简单一句就是&#xff1a;如果一个或多个对象没有任何的引用指向它了&#xff0c;那么这个对象现在就是垃圾&#xff0c;如果定位了垃圾&#xff0c;则有可能会被垃圾回收器回收。 如果要定位什么是垃圾&#xff0c;有两…

分布式锁-快速入门

文章目录 前言一、基础概念1.1 什么是锁1.2 什么是分布式锁1.3 锁和事务的区别二、分布式锁基础理论2.1 为什么要使用分布式锁2.2 分布式锁特性2.3 分布式锁的实现方式总结前言 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题…

TRILL解析

Deep Imitation Learning for Humanoid Loco-manipulation through Human Teleoperation解析 摘要1.简介2. Related work2.1 人形机器人的局部操纵2.2 远程操作示范中的模仿学习 3. 方法 论文链接&#xff1a;https://arxiv.org/abs/2309.01952 论文项目&#xff1a;https://ut…

通过mask得到bbox(numpy实现)

在SAM的加持下&#xff0c;我们很容易得到物体的mask&#xff0c;但是物体的bbox信息通常也很有用。那么&#xff0c;我们可以写一个函数&#xff0c;立马可以通过mask得到bbox。 代码如下&#xff1a; import numpy as npdef mask2bbox(mask):nonzero_indices np.nonzero(m…

运维开发工程师教程之MongoDB单机版设置

MongoDB单机版设置 一、创建虚拟机 在VMware Workstation软件中新建一个虚拟机&#xff0c;具体操作步骤如下&#xff1a; ①运行VMware Workstation软件&#xff0c;进入到主界面&#xff0c;单击“创建新的虚拟机”来创建新的虚拟机&#xff0c;如图3-1所示。 图3-1 VMware…

Anaconda安装教程

1Anaconda 简介 Anaconda是一个数据科学平台&#xff0c;提供一个发行版的 Python 以及大量常用的数据科学包、库和工具。通过包含诸如 NumPy、Pandas、SciPy、Matplotlib等核心库&#xff0c;以及 Jupyter Notebook等开发工具&#xff0c;使数据分析、机器学习和数据可视化变…

stm32和树莓派的区别?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「stm32的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;Stm32和树莓派是两个不同的领域…

百度副总裁秒批离职,00后的职场逆袭?

“员工闹分手提离职我秒批”&#xff0c;百度副总裁璩静的职场经历和思考在近期引发了大量讨论。 璩静在小红书分享了自己作为女性管理者&#xff0c;面对团队内部的感情问题&#xff0c;是如何处理的&#xff1a; “我第一时间就跟这个年轻的女孩子说&#xff0c;你走吧&…

18、ESP32 ESP-NOW 点对点通信

ESP-NOW 是乐鑫自主研发的无连接通信协议&#xff0c;具有短数据包传输功能。该协议使多个设备能够以简单的方式相互通信。 ESP-NOW 功能 ESP-NOW 支持以下功能&#xff1a; 加密和未加密的单播通信;混合加密和未加密的对等设备;最多可携带 250 字节 的有效载荷;发送回调功能…

【EasySpider】EasySpider+mysql执行配置异常

问题 使用易采集工具操作时候&#xff0c;遇到一个执行异常&#xff0c;后来发现没有选择数据类型 Loading stealth.min.js MySQL config file path: ./mysql_config.json 成功连接到数据库。 Successfully connected to the database. Traceback (most recent call last):…