STL_vector源码剖析

STL vector

STL2.91源码地址: https://github.com/lewischeng-ms/sgi-stl
侯捷老师用的是 2.91,不同版本的STL差异很大,靠后版本的STL用了太多typedef以及继承关系,导致可读性很差。
本文参考博客: https://blog.csdn.net/weixin_45389639/article/details/121618243

vector 源码

// vector源码
template<class T,class Alloc=alloc>
class vector
{
public:
	typedef T value_type;
	typedef value_type* iterator;
	typedef value_type& reference;
	typedef size_t size_type;
protected:
	iterator start;
	iterator finish;
	iterator end_of_storage;
public:
	iterator begin(){return start;}
	iterator end(){return finish;}
	size_type size()const{return (size_type)end_of_storage-begin();}
	bool empty()const{return begin()==end();}
	reference operator[](size_type n){
		return *(begin()+n);
	}
	reference front(){return *begin();}
	reference back(){return *(end()-1);}
    ...
};

vector源码分析

vector中定义了三个指针: start 、finish 、 end_of_storage
sizeof(vector): 三个指针的大小
在这里插入图片描述

vector扩容:空间两倍增长

​ vector容器的迭代器start指向第一个元素,finish指向最后一个元素的下一个元素,满足了前闭后开特性,end_of_storage是vector的容量。vector在使用上是连续的,在实现上也是连续的,所以迭代器采用non-class类型。

// vector源码
template<class T,class Alloc=alloc>
class vector
{
public:
	typedef T value_type;
	typedef value_type* iterator;
	typedef value_type& reference;
	typedef size_t size_type;
protected:
	iterator start;
	iterator finish;
	iterator end_of_storage;
public:
	iterator begin(){return start;}
	iterator end(){return finish;}
	size_type size()const{return (size_type)end_of_storage-begin();}
	bool empty()const{return begin()==end();}
	reference operator[](size_type n){
		return *(begin()+n);
	}
	reference front(){return *begin();}
	reference back(){return *(end()-1);}
    ...
};

vector.push_back()的方法,首先会判断end_of_storage是不是满了,满了的话就会扩容2倍再进行添加元素。注意:扩充的过程重并不是在原有空间后面追加容量,而是重新申请一块连续的内存空间,将原有的数据拷贝到新空间中,再释放原来空间中内存。所以扩充之后,原有的迭代器将会失效!

  void push_back(const T& x) {
    if (finish != end_of_storage) {
      construct(finish, x);
      ++finish;
    }
    else
      insert_aux(end(), x);
  }

​insert_aux是vector容器用来在内部任意位置插入元素,内存不足的情况下会扩容。

template<class T, class Alloc>
void vector<T, Alloc>::insert_ux(iterator position, const T &x) {
    if (finish != end_of_storage) {     // 尚有备用空间,则将插入点后元素后移一位并插入元素
        construct(finish, *(finish - 1));   // 以vector最后一个元素值为新节点的初值
        ++finish;
        T x_copy = x;
        copy_backward(position, finish - 2, finish - 1);
        *position = x_copy;
    } else {
        // 已无备用空间,则先扩容,再插入
        const size_type old_size = size();
        const size_type len = old_size != 0 ?: 2 * old_size:1;  // 扩容后长度为原长度的两倍

        iterator new_start = data_allocator::allocate(len);
        iterator new_finish = new_start;
        try {
            new_finish = uninitialized_copy(start, position, new_start);    // 拷贝插入点前的元素
            construct(new_finish, x);                                       // 插入新元素并调整水位
            ++new_finish;
            //这个辅助还是不止被push_back调用,其他函数(insert)也会调用。 insert插入需要扩充数据,会有安插点之前和安插点之后
            //需要将安插点之后的元素也拷贝过来
            new_finish = uninitialized_copy(position, finish, new_finish);  // 拷贝插入点后的元素
        }
        catch (...) {
            // 插入失败则回滚,释放内存并抛出错误
            destroy(new_start, new_finish) :
            data_allocator::deallocate(new_start, len);
            throw;
        }
        // 释放原容器所占内存
        destroy(begin(), end());
        deallocate();
        // 调整迭代器
        start = new_start;
        finish = new_finish;
        end_of_storage = new_start + len;
    }
};

vector迭代器

列表的迭代器设置为class,因为列表的节点都是分离的
vector用指针就可以当作迭代器

class vector {
public:
  typedef T value_type;
  typedef const value_type* const_pointer;
  typedef value_type* iterator;
  };
  -------------------------------------------------
  //使用迭代器
  vector<int> vec;
  vecto<int>::iterator it = vec.begin();

算法使用vec的迭代器,需要知道迭代器的5个参数会将value_type* iterator迭代器丢给traits,
traits使用指针偏特化的版本 iterator_traits<T>*、

这一部分需要对萃取有一些了解: https://editor.csdn.net/md/?articleId=138084134
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker NetWork (网络)

Docker 为什么需要网络管理 容器的网络默认与宿主机及其他容器都是相互隔离的&#xff0c;但同时我们也要考虑下面的一些问题&#xff0c; 比如 多个容器之间是如何通信的容器和宿主机是如何通信的容器和外界主机是如何通信的容器中要运行一些网络应用(如 nginx、web 应用、数…

【Linux系统编程】第七弹---权限管理操作(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、修改文件权限的做法(一) 2、有无权限的表现 总结 上一弹我们讲解了Linux权限概念相关的知识&#xff0c;但是我们只知道有…

设计模式学习笔记 - 开源实战四(中):剖析Spring框架中用来支持扩展的设计模式

概述 上篇文章&#xff0c;学习了 Spring 框架背后蕴含的设计思想&#xff0c;比如约定优于配置、低侵入松耦合、模块化轻量级等等。这些设计思想可以借鉴到其他框架开发中&#xff0c;在大的设计层面提高框架的代码质量。 除了上篇文章降到的设计思想&#xff0c;实际上&…

yolov8 裁剪检测结果

yolov8 裁剪检测结果 1. 基础2. 图片批量裁剪2.1 检测裁剪2.2 分割裁剪 3. 视频裁剪3.1 检测裁剪3.2 分割裁剪3.3 实时裁剪 4. 源码 1. 基础 本项目是在 WindowsYOLOV8环境配置 的基础上实现的 思路&#xff1a;将检测得到的物体边框提取&#xff0c;然后边框裁剪原图&#xf…

Python网络数据抓取(3):Requests

引言 在这一部分&#xff0c;我们将探讨Python的requests库&#xff0c;并且利用这个库来进行网页数据抓取。那么&#xff0c;我们为何需要这个库&#xff0c;以及怎样利用它呢&#xff1f; requests库是广受大家欢迎的一个库&#xff0c;它是下载次数最多的。这个库使我们能够…

直流负载在新能源领域的作用有哪些

直流负载在新能源领域的作用主要体现在以下几个方面&#xff1a; 新能源如太阳能、风能等&#xff0c;其发电过程中产生的电能为直流电。传统的电力系统主要采用交流电&#xff0c;因此在新能源并网时需要进行逆变器转换。然而&#xff0c;逆变器在转换过程中会存在一定的能量损…

设计模式-模板模式

模板设计模式 定义 在模板模式中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。 简单来说,有多个子类共有的方法,且逻辑相同,可以考虑作为模板方法。 模板的价值就在于骨架的定义,骨架内部将问题…

手写基于redis-lua脚本实现分布式id生成器starter

手写基于redis-lua脚本实现分布式id生成器starter 文章目录 1.前言2.实现思路2.1lua脚本的特性2.2 了解三个redis命令2.3集群自增序列实现原理2.4三种实现思路2.4.1 实现思路一2.4.2 实现思路二2.4.3实现思路三 3.项目工程目录4.源码仓库地址5.依赖及使用配置5.1依赖5.2nacos配…

科研基础与工具(论文写作)

免责申明&#xff1a; 本文内容只是学习笔记&#xff0c;不代表个人观点&#xff0c;希望各位看官自行甄别 参考文献 科研基础与工具&#xff08;YouTube&#xff09; 学术写作句型 Academic Phrase bank 曼彻斯特大学维护的一个网站 写论文的时候&#xff0c;不不知道怎么…

机器学习基础-PR\ROC\F1

1 1 、ROC曲线2 、PC曲线3、F14 、正负样本不均衡时怎么选择 1 、ROC曲线 就是TPR 与FPR 曲线 如图&#xff0c;就是根据阈值不同&#xff0c;我们看我们的二分类器的结果&#xff0c;根据结果算出TPR(真阳性)与FPR(假阳性)&#xff0c;最好的情况就是如图&#xff0c;我们的…

2024年三支一扶报名照上传要求很严格

2024年三支一扶报名照上传要求很严格

2024年最新版云开发cms开通步骤,开始开发微信小程序前的准备工作,认真看完奥!

小程序官方有改版了&#xff0c;搞得石头哥不得不紧急的再新出一版&#xff0c;教大家开通最新版的cms网页管理后台 一&#xff0c;技术选型和技术点 1&#xff0c;小程序前端 wxml css JavaScript MINA原生小程序框架 2&#xff0c;数据库 云开发 云数据库 云…

合合信息Embedding模型:引领中文文本向量化技术新高度

目录 &#x1f345;前言&#x1f353;赛事含金量&#x1f353;Embedding技术简介&#x1f353;Embedding在大模型中的价值&#x1f353;合合信息Embedding模型特点及优势&#x1f353;合合信息Embedding模型测试&#x1f353;技术突破&#x1f353;公司介绍 &#x1f345;总结 …

360在线翻译免费API

一、需求&#xff1a; 根据360在线翻译&#xff0c;获取免费API&#xff0c;并调用 二、主要步骤 1、请求 url url "https://fanyi.so.com/index/search" 2、传入信息 datas {"query": "桌子"} 3、请求头 headers {"pro": &…

Axure糖尿病健康管理APP原型 (知识科普/病友社区/远程医生会诊/购物商城/血糖监测/饮食监测)

作品概况 页面数量&#xff1a;共 50 页 源文件格式&#xff1a;rp格式&#xff0c;兼容 Axure RP 9/10&#xff0c;非程序软件无源代码 应用领域&#xff1a;医疗健康、慢病管理、糖尿病管理 作品特色 本作品为Axure糖尿病健康管理APP端原型图&#xff0c;设计规范内容清晰…

第54篇:创建Platform Designer系统

Q&#xff1a;本期我们开始使用Platform Designer工具创建带IP核的FPGA自定义硬件系统。 A&#xff1a;Platform Designer是集成在Quartus软件里的系统设计工具&#xff0c;名称随着Quartus的不断更新曾命名为SOPC Builder和Qsys。 使用Platform Designer可以添加Quartus已有自…

Aigtek高压放大器在电活性聚合物中的作用是什么

电活性聚合物是一类特殊类型的聚合物&#xff0c;其性质和形状可以受到外部电场的调控。这些聚合物在多个领域中有着广泛的应用&#xff0c;包括人工肌肉、电动液体透镜、柔性电子、生物医学传感器等。高压放大器在电活性聚合物的研究和应用中扮演着关键的角色&#xff0c;下面…

【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明 文章编号&am…

C#-使用Harmony库实现DLL文件反射调用

一. Harmony工作原理 利用C#运行时Runtime的反射机制,动态加载dll中的方法,字段,属性,实现对DLL方法的重写和代码注入。 二. Harmony下载及安装 1.下载Harmony_lib库lib.harmony.2.3.3.nupkg 霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharph…

南京邮电大学数学实验A答案 | 《MATLAB数学实验》第三版课后习题答案

数学实验A 本仓库收集了2024年我在学习《数学实验A》课程期间完成的作业。课程使用的教材为《MATLAB数学实验》第三版&#xff0c;作者为胡良剑和孙晓君教授。 这个资源库的建立初衷是为了帮助南京邮电大学的同学们在学习过程中有一个参考的依据&#xff0c;减少一些无端浪费…