vector的底层与使用

news2024/9/25 19:25:43

前言:vector是顺序表(本质也是数组)

文档参考网站:https://legacy.cplusplus.com/reference/vector/vector/vector/

//底层代码
#include<assert.h>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
namespace bit
{
	template<typename T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		template <typename InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			reserve(last - first);
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
		
			
		vector(int size = 1)
		{
			_begin = _end = new T[size];
			_endofstorage = _begin + size;
		}
		~vector()
		{
			delete[] _begin;
			_begin = _end = _endofstorage = nullptr;
		}
		vector(const vector<T>& s)
		{
			reserve(s.capacity());
			for (auto& e : s)
				push_back(e);
		}
		int size() const
		{
			return _end - _begin;
		}
		int capacity() const
		{
			return _endofstorage - _begin;
		}
		void reserve(int newcapacity)
		{
			if (newcapacity > capacity())
			{
				int old_size = size();
				iterator tmp = new T[newcapacity];
				for(int i = 0 ; i < old_size ; i++)
                {
                     tmp[i] = _begin[i];
                }
                //不能用memcpy,防止数据进行浅拷贝
				_begin = tmp;
				_end = tmp + old_size;
				_endofstorage = tmp + newcapacity;
			}
		}

		void push_back(T val)
		{
			int old_size = size();
			if (_end == _endofstorage)
			{
				reserve(2 * old_size);
			}
			*_end = val;
			_end++;
		}
		iterator begin() //返回临时变量
		{
			return _begin;
		}
		iterator end()
		{
			return _end;
		}
		const_iterator begin() const
		{
			return (const_iterator)_begin;
		}
		const_iterator end() const 
		{
			return (const_iterator)_end;
		}
		void pop_back()
		{
			_end--;
		}
		
		
		iterator insert(iterator position, const T& val)
		{
			assert(position < _end);
			iterator tmp = _end;
			if (_end == _endofstorage) {
				size_t len = position - _begin;
				reserve(2 * size());
				position = _begin + len;
			}
			while (_end != position)
			{
				*_end = *(_end - 1);
				_end--;
			}
			iterator k = _end;
			*_end = val;
			_end = tmp;
			_end++;
			return k;
		}
		T& operator[] (int n)
		{
			assert(n < size());
			return _begin[n];
		}
		const T& operator[] (int n) const
		{
			assert(n < size());
			return _begin[n];
		}
		iterator erase(iterator position)
		{
			assert(position < _end);
			iterator tmp = position;
			while (position != _end)
			{
				*(position) = *(position + 1);
				position++;
			}
			_end--;
			return tmp;
		}
		iterator erase(iterator first, iterator last)
		{
			assert(last < _end && first < _end);
			int a = last - first;
			iterator tmp = last;
			iterator k = first;
			while (tmp != _end)
			{
				*first = *tmp;
				tmp++;
				first++;
			}
			_end -= a;
			return k;
		}
		void clear()
		{
			_end = _begin;
		}
		void resize(int n, const T& val = T())
		{
			int _size = size();
			if (n > _size)
			{
				reserve(n);
				iterator t = _begin + n;
				while (_end != t)
				{
					*_end = val;
					_end++;
				}
			}
			else
			{
				_end = _begin + n;
			}
		}
	private:
		iterator _begin = nullptr;//初始化列表
		iterator _end = nulptr;
		iterator _endofstorage;
	

	};
}

构造函数

第一种方式: vector( int size = 1 )// 全缺省,作为默然构造函数

 开10个整形的数组

第二个方式:vector( int size , const T& val = T() )

解释 T()        当T为自定义类型时,调用T的默然构造函数

                      但对于内置类型,编译器会自动调用内置类型的默然构造(纯粹为了符合类模版)

                       对于int 为 0  , 对于double 为 0.0 ,对于char 为 '\0' , 对于指针为nullptr等

第三种方式:运用类成员函数模版

template <class InputIterator>
  vector (InputIterator first, InputIterator last) 左闭右开

第四种方式:C++11提出的(用初始化链表初始化)

  

e的类型是初始化链表

初始化链表只有四个接口函数 , 初始化链表只能支持遍历 ,不能支持赋值,初始化链表中的数据储存在常量区中(不能被修改)

析构函数

底层实现简单  ( clear 函数 + 指针置为空指针 )

这里补充一下clear函数

void clear()
{

_end = _begin;

}

~vector()
{

clear();

delete[] _begin;

_begin = _end = _endofstorage = nullptr;
}

拷贝构造函数(深拷贝)

现代写法:

vector( const vector<T> & s )
{

        reserve(s.capacity());//提前开好空间

        for( auto& e : s )//使用引用,防止拷贝构造,提升效率
        {

        push_bakc(e);//注意数据要进行深拷贝
        }
}

迭代器

由于物理空间上连续,与指针的行为相似

typedef T* iterator ;

typedef const T* const_iterator;

要注意*this是const成员还是非const成员

iterator begin()
{
        return _begin;
}

iterator end()
{
return _end;

}

const_iterator begin()const
{
       return (const T*) _begin;
}

const_iterator end() const
{

return (const T*)_end;

}

const T& operator[](int npos) const 
{

assert( npos < size() );//注意未初始化的地方不能使用
return _begin[npos];

}

 T& operator[](int npos) 
{

assert( npos < size() );
return _begin[npos];

}

运算符重载

vector<T>& operator=(  vector<T>  s) (构造 加 交换 )
{
       swap(s,*this);

       return *this;
}

insert函数

主要是在某个位置之前插入一个值或一段区间

样列:

#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(5);
    s.insert(s.begin() + 1, 10);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

样列:

#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(5);
    string k("asdfasfsaf");
    s.insert(s.begin() + 1, k.begin() + 2 , k.end() - 4);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

erase函数(一般不会缩容)

删除某个位置的值 , 或删除一段区间的值(左闭右开)

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    vector<int> s;
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.erase(s.begin(), s.end() - 1);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

注意在使用insert函数和erase函数会造成迭代器失效,所以在使用完迭代器之后,就不能在使用,

如果你就要使用,则要更新迭代器

举个例子:(删除顺序表中的偶数)

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(4);
    s.push_back(9);
    s.push_back(11);
    s.push_back(11);
    s.push_back(11);
    auto it = s.begin();
    while (it != s.end())
    {
        if (*it % 2 == 0)it = s.erase(it);
        else it++;
    }
    for (auto& e : s)cout << e << " ";
    cout << endl;
    return 0;
}

push_back 和 pop_back

尾增 和 尾删

reserve和resize函数

reserve函数时扩容,reserve使用完,不能用[]赋值

resize函数是扩容(当newcapacity > newcapacity) + 初始化

要注意reserve函数在完成扩容时,是对数据进行深拷贝(不能使用memcpy)

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

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

相关文章

跳跃游戏 II (贪心, 动态规划)

题目描述(力扣45题) : 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到…

学会了这几点,制作电子杂志原来这么简单

​电子杂志作为一种新型的出版形式,正在逐渐受到大众的欢迎。而制作电子杂志,其实并没有想象中那么困难。下面,我们就来学习这几点,让电子杂志制作变得简单易学。 1.要制作电子杂志,首先需要选择一款适合自己的软件。比如FLBOOK在线制作电子杂志平台。这个工具具有强大的功能,可…

“傻瓜”学计量——核密度估计KDE

提纲&#xff1a; 什么是核密度估计&#xff0c;是干什么的 代码 1 前言 参数估计vs非参数估计参数估计是样本数据来自一个具有明确概率密度函数的总体。非参数估计是样本数据的概率分布未知&#xff0c;这时&#xff0c;为了对样本数据进行建模&#xff0c;需要估计样本数据…

DDP、pytorch的分布式 torch.distributed.launch 训练说明

0、DDP的运行原理 执行步骤&#xff1a; 将data分为多个不同的batch&#xff0c;每个gpu得到batch都是不一样的然后将每个batch放在每个gpu上独立的执行最后得到的梯度求平均将平均梯度平分给每个gpu执行下一次迭代 这也就意味着你有多少个gpu&#xff0c;训练的速度也会提升…

Redis中的慢查询日志和监视器

慢查询 添加新日志 在每次执行命令的之前和之后&#xff0c;程序都会记录微妙格式的当前UNIX时间戳&#xff0c;这两个时间戳之间的差就是服务器执行命令所耗费的时长&#xff0c;服务器会将这个时长作为参数之一传给slowlogPushEntryIfNeeded函数&#xff0c;而slowlogPushE…

【Git】生成patch和应用patch

生成patch 将本地所有修改打成补丁 git diff > /tmp/xxx.patch将本地对某个文件的修改打成补丁 git diff test/1.txt > /tmp/1.patch将某一次提交的修改内容打成补丁 -1表示只为单个提交创建patch&#xff0c;-o表示输出patch的文件夹路径&#xff0c;默认是用提交的…

[LitCTF 2023]PHP是世界上最好的语言!!、 [LitCTF 2023]Vim yyds、 [羊城杯 2020]easycon

目录 [LitCTF 2023]PHP是世界上最好的语言&#xff01;&#xff01; [LitCTF 2023]Vim yyds [羊城杯 2020]easycon [LitCTF 2023]PHP是世界上最好的语言&#xff01;&#xff01; 无参&#xff0c;根据题目提示看看php能否执行——返回1执行成功 用system()函数调用、执行ls …

【每周精选资讯 | 第 6 期】2024-04-15 ~ 2024-04-21

目录 前言内容国家天文台推出新一代天文大模型“星语3.0”李飞飞团队发布《2024年人工智能指数报告》&#xff0c;揭示AI十大趋势百度发布新一代智能计算操作系统“万源”刘强东AI数字人“采销东哥”亮相直播抖音与美团在AI赋能本地生活服务领域的竞争与合作联想发布AI PC系列产…

说话的艺术

目录&#xff1a; 1、询问术 2、说话的逻辑性 1、询问术 询问类似于从对方检索出你想要得到的事情&#xff0c;做好笔记也是很有必要的&#xff0c;故将“询问术”放于此处。 把握&#xff1a;26/F*4超级询问 2&#xff1a;带着两岁孩童的好奇心去提问 6&#xff1a;使用…

SpringCloud系列(9)--将服务消费者Consumer注册进Eureka Server

前言&#xff1a;上一章节我们介绍了如何将服务提供者注册进Eureka服务里&#xff0c;本章节则介绍如何将服务消费者Consumer注册进Eureka服务里 Eureka架构原理图 1、修改consumer-order80子模块的pom.xml文件&#xff0c;引入Eureka Clinet的依赖&#xff0c;然后reolad一下&…

Springboot 初始化操作

文章目录 程序启动后的初始化ApplicationRunner 接口CommandLineRunner 接口ApplicationRunner 和CommandLineRunner 的区别 Bean的实例化InitializingBean 接口PostConstruct注解BeanInitializingBean 接口、PostConstruct注解、Bean注解区别 总结 前些天发现了一个巨牛的人工…

晨控电子纸,工业无纸化新方案

一款好的产品&#xff0c;应该用心的去介绍。随着工业科技不断的迭代&#xff0c;生产车间自动化程度越来越高&#xff0c;但很多工序还是需要人员去更换&#xff0c;确认生产流程单。由于人员确认流程单的不确定性&#xff0c;很有可能出现流程单信息错误&#xff0c;下一工序…

Excel文件解析--超大Excel文件读写

使用POI写入 当我们想在Excel文件中写入100w条数据时&#xff0c;我们用普通的XSSFWorkbook对象写入时会发现&#xff0c;只有在将100w条数据全部加载入内存后才会用write()方法统一写入&#xff0c;这样效率很低&#xff0c;所以我们引入了SXSSFWorkbook进行超大Excel文件的读…

《ElementUI 基础知识》png 图片扩展 icon用法

前言 UI 设计给的切图是 .png 格式。但想与 Element UI icon 用法类似&#xff0c;方案如下。 实现 步骤一 准备图片 步骤二 新建文件&#xff0c;可使用 CSS 预处理语言 styl 或 scss。 stylus 方式 文件 icon.styl /* 定义一个混合 */ cfgIcon(w, h) {display: inlin…

二叉搜索树中的搜索(力扣700)

解题思路&#xff1a;因为二叉搜索树的左小右大特点&#xff0c;中只是寻找比较目标&#xff0c;怎么序遍历都可以&#xff0c;终止条件就是遍历完毕和找到了&#xff0c;然后就遍历左右子树开始寻找就好了 具体代码如下: class Solution { public: TreeNode* searchBST(Tre…

Java入门四步走

1. 简单的入门语法&#xff1a; 1.1 数据类型&#xff1a; 基本数据类型&#xff1a; 整数类型 —— byte、short、int、long, 浮点类型 —— float、double 字符类型 —— char 布尔类型 —— boolean 引用数据类型&#xff1a; 接口&#xff08;interface&#xff09;、数…

上市公司-企业数据要素利用水平数据集及参考文献(2010-2022年)

01、数据介绍 企业数据要素利用水平是指企业在其生产经营活动中&#xff0c;对数据的收集、处理、分析和应用的能力及效果。这种利用水平的高低直接反映了企业在数字化时代中的竞争力和创新能力。 本数据参考《中央财经大学学报》史青春&#xff08;2023&#xff09;老师的研…

芒果超媒的“乘风破浪”,差了一点市场海浪的反馈

4月21日晚间&#xff0c;芒果超媒发布了2023年度&2024一季度报告。 芒果超媒2023年实现营业收入146.28亿元&#xff0c;同比增长4.66%&#xff1b;净利润35.56亿元&#xff0c;同比增长90.73%&#xff1b;基本每股收益1.90元。公司拟每10股派发现金红利1.8元。2024年第一季…

使用gdal均匀筛选点矢量

使用gdal均匀筛选点矢量 作用&#xff1a; 通过计算各点之间的欧式距离&#xff0c;筛选出符合目标的、均匀发布在空间中的N个数据点。 效果示意图 运行环境 python 3.10 安装&#xff1a;tqdm、numpy和tqdm这三个库 完整代码 import numpy as np from osgeo import ogr,…

291个地级市资源错配指数、劳动和资本相对扭曲指数(2006-2021年)

01、数据介绍 资源错配指数&#xff08;Misallocation Index&#xff09;是一个用于衡量资源配置效率的指标&#xff0c;它衡量的是生产要素的配置是否合理&#xff0c;是否达到了最优的状态。资源错配指数越高&#xff0c;资源的利用效率越低。资源错配指数主要用于衡量各种生…