vector的使用和底层模拟实现

news2024/11/25 22:44:58

爱吃喵的鲤鱼

个人主页

文章目录

  • 前言
  • 一、pandas是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.读入数据
  • 总结


前言

我们已经 学习了string在来实现vector会发现他们两的结构很像,而string只支持存储字符串,vector支持任意类型;


一、vector是什么?

vector和string都一样,是c++的容器,两个的差别在于vector存储的是任意类型,string是字符串。底层结构也有所不同,string数据结构和数组相似,而vector使用3个指针控制的。

二、vector的使用

2.常用的函数代码演示

1、迭代器的使用

void func(const vector<int>& vv)
{
	vector<int>::const_iterator it = vv.begin();
	for (size_t i = 0; i < vv.size(); i++)
	{
		cout << vv[i] << " ";
	}
	cout << endl;
	while (it != vv.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	for (auto i : vv)
	{
		cout << i << " ";
	}
	cout << endl;
	
}

其实大家经常使用的范围for也是迭代器的使用;

2、常用的修改器

vector<int> vv;
vv.push_back(1);
vv.push_back(2);
vv.push_back(3);
vv.push_back(4);
vector<int>::iterator pos = find(vv.begin(), vv.end(), 2);
if (pos == vv.end())
{
	vv.insert(pos, 30);
}
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;

vv.resize(20,0);//开20个空间并且初始化
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
vv.push_back(20);//尾插
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
vv.pop_back();
vv.pop_back();
vv.pop_back();
for (int i = 0; i < 10; i++)//循环尾删10次
{
	vv.pop_back();
}
for (auto i : vv)//打印元素
{
	cout << i << " ";
}
cout << endl;
auto it = vv.begin();
//删除偶数
while (it != vv.end())
{
	if (*it % 2 == 0)
	{
		it = vv.erase(it);//删除it位置元素

	}
	else
		it++;
}
for (auto i : vv)
{
	cout << i << " ";
}
}

3、容量

已经在上面两类中体现了 

三、底层模拟实现

1、vector构架

	template<class T>//因为vector可以容下任意类型,所以我们构建了一个模板类
class vector
{
public:
	typedef T* iterator;//对迭代器的声名
	typedef const T* const_iterator;//对const迭代器的声名
	vector()//构造函数
		:_start(nullptr)
		, _finish(nullptr)
		, _end_of_storage(nullptr)
	{}
		~vector()//析构函数
		{
			delete[]_start;
			_start = _finish = _end_of_storage = nullptr;
		}
		vector(size_t n,const T& val=T())//构造函数
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		vector(int n, const T& val = T())//构造函数
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{

			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}
		}		
vector(const vector<T>& v)//拷贝构造
		{
			//reserve(capacity());
			_start = new T[capacity()];
			//memcpy(_start, v._start, sizeof(T)*v.size());//
			for (size_t i = 0; i < v.size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_end_of_storage = _start + v.capacity();
		}
private:
		//左闭右开区间
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};

在我们的拷贝构造中涉及了一个深浅拷贝问题;

什么是深浅拷贝 ?

浅拷贝只是对成员变量进行了拷贝 

浅拷贝就是我们只对一块内存空间的地址进行拷贝,这个时候就会有两个指针变量指向了同一块空间,当我们对第一个成员进行析构时,这空空间已经被释放了,第二个变量再来这里析构就会让程序崩溃;

深拷贝是两块不同的空间 

深拷贝是在开辟一块空间,将原有内存中的数据一个个的拷贝到新空间中;

2、vector的迭代器函数

bool empty()//判断是否为空
{
	return _start == _finish;
}
size_t capacity() const
{
	return _end_of_storage - _start;
}
size_t size() const
{
	return _finish - _start;
}
const T& operator[](size_t pos) const
{
	assert(pos < size());
	return _start[pos];
}
size_t capacity()
{
	return _end_of_storage - _start;
}
size_t size()
{
	return _finish - _start;
}
T& operator[](size_t pos)
{
	assert(pos < size());
	return _start[pos];
}
iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}
const iterator begin() const
{
	return _start;
}
const iterator end() const
{
	return _finish;
}

迭代器中判断大小主要用的是地址-地址,因为一段连续的空间,地址-地址就是它的大小;

这些函数在后面使用时,我们会用到const的类型,所以构造了const的函数 

3、修改器的模拟实现

		iterator insert(iterator pos, const T& val = T())//在任意位置插入
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}
			iterator end = _finish - 1;//没有这个会有迭代器失效,就是构成野指针
			while (end >= pos)
			{
				
				*(end + 1) = *end;
				end--;
			}
			*pos = val;
			_finish++;
			return pos;//以后还可以在次使用
		}

		void resize(size_t n,const T& val=T())//开空间初始化
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}

		}
		iterator erase(iterator pos)//erase不在访问这块空间
		{
			assert(pos < _finish);
			assert(pos >= _start);
			iterator start = pos + 1;
			while (start != _finish)
			{
				*(start-1) = *start;
				start++;
			}
			_finish--;
			return pos;
		}
	void reserve(size_t n)//开辟n个空间
	{
		if (n > capacity())
		{
			size_t sz = size();
			T* tmp = new T[n];
			if (_start)
			{
				memcpy(tmp, _start, sizeof(T) * size());
			/*	for (size_t i = 0; i < size(); i++)
				{
					_start[i] = tmp[i];
				}*/
				delete[] _start;
			}
			_start = tmp;
			_finish = tmp + sz;
			_end_of_storage = tmp + n;
		}
	}
	void push_back(const T& x)//尾插
	{
		if (_finish == _end_of_storage)
		{
			reserve(capacity() == 0 ? 4 : capacity() * 2);
		}
		*_finish = x;
		_finish++;
	}
	void pop_back()//尾删
	{
		assert(!empty());
		_finish--;
	}

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

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

相关文章

3. Django 初探路由

3. 初探路由 一个完整的路由包含: 路由地址, 视图函数(或者视图类), 可选变量和路由命名. 本章讲述Django的路由编写规则与使用方法, 内容分为: 路由定义规则, 命名空间与路由命名, 路由的使用方式.3.1 路由定义规则 路由称为URL (Uniform Resource Locator, 统一资源定位符)…

-bash: cd: /etc/hadoop: 没有那个文件或目录

解决办法&#xff1a;source /etc/profile 运行 source /etc/profile 命令会重新加载 /etc/profile 文件中的配置&#xff0c;这样做的目的是使任何更改立即生效&#xff0c;而不需要注销并重新登录用户。通常&#xff0c;/etc/profile 文件包含系统范围的全局 Shell 配置&…

电商社交新零售:创新引领新趋势,变革新零售思维格局-亿发

新零售O2O模式是如何颠覆传统零售商业模式&#xff1f; 传统电商出现瓶颈&#xff1a; 传统电商在发展过程中逐渐出现了瓶颈&#xff0c;主要表现在市场竞争激烈、用户获取成本上升、用户黏性下降等问题。传统电商往往只能通过价格竞争或促销活动来吸引用户&#xff0c;而这种…

hexo接入github Discussions评论系统

评论存储仓 可以是你的博客项目的(github)仓库&#xff0c;也可以单独新建一个评论存储仓库。 我的博客项目在gitee上&#xff0c;就以新建存储仓为例&#xff1a; 使用Discussions评论系统必须开通Discussions模块&#xff01; 安装giscus插件 https://github.com/apps/…

数据仓库发展历史与架构演进

从1990年代Bill Inmon提出数据仓库概念后经过四十多的发展&#xff0c;经历了早期的PC时代、互联网时代、移动互联网时代再到当前的云计算时代&#xff0c;但是数据仓库的构建目标基本没有变化&#xff0c;都是为了支持企业或者用户的决策分析&#xff0c;包括运营报表、企业营…

vscode中vue插件

在Visual Studio Code (VSCode) 中&#xff0c;有许多插件可以帮助Vue开发者提高工作效率和代码质量。以下是一些针对Vue开发的必备VSCode插件&#xff0c;结合了多篇搜索结果中的信息&#xff0c;以提供详尽的介绍。 Volar Volar是Vue.js开发者的官方推荐插件&#xff0c;专门…

python基于opencv实现数籽粒

千粒重是一个重要的农艺性状&#xff0c;通过对其的测量和研究&#xff0c;我们可以更好地理解作物的生长状况&#xff0c;优化农业生产&#xff0c;提高作物产量和品质。但数籽粒数目是一个很繁琐和痛苦的过程&#xff0c;我们现在用一个简单的python程序来数水稻籽粒。代码的…

React之基础项目搭建

前言 React的生态系统非常庞大&#xff0c;拥有大量的第三方库和工具&#xff0c;如React Native&#xff08;用于构建原生移动应用&#xff09;、Next.js&#xff08;用于构建服务器渲染应用&#xff09;、Create React App&#xff08;用于快速搭建React应用的脚手架&#x…

【机器学习300问】62、若想将逻辑回归用于多分类有哪些常见做法?

逻辑回归算法在设计之初是用于二分类问题的&#xff0c;但若想把它用在多分类上也不是不行&#xff0c;这得看你具体面临的多分类问题是什么样的&#xff08;问题的定义&#xff09;。不同的问题就有不同的应对之策&#xff1a; 一、一对一 &#xff08;1&#xff09;方法的原…

【JavaEE】_Spring MVC项目获取Header

目录 1. 使用Servlet原生方法获取Header 2. 使用Spring注解获取Header 1. 使用Servlet原生方法获取Header .java文件内容如下&#xff1a; package com.example.demo.controller;import com.example.demo.Person; import org.springframework.web.bind.annotation.*; impor…

Linux-等待子进程

参考资料&#xff1a;《Linux环境编程&#xff1a;从应用到内核》 僵尸进程 进程退出时会进行内核清理&#xff0c;基本就是释放进程所有的资源&#xff0c;这些资源包括内存资源、文件资源、信号量资源、共享内存资源&#xff0c;或者引用计数减一&#xff0c;或者彻底释放。…

14届蓝桥杯 C/C++ B组 T5 接龙排序 (最长上升子序列DP+优化)

不难发现这是一个LIS问题&#xff0c;但是如果直接套用LIS的模版&#xff0c;在数据范围到达 1 e 5 1e5 1e5 的情况下&#xff0c;就只能够得到一半的分数&#xff0c;所以我们需要对其进行优化。 首先给出暴力的代码&#xff1a; #include<iostream> using namespace…

python+django教师业绩考评考核评分系统flask

在设计过程中&#xff0c;将参照一下国内外的一些同类网站&#xff0c;借鉴下他们的一些布局框架&#xff0c;将课题要求的基本功能合理地组织起来&#xff0c;形成友好、高效的交互过程。开发的具体步骤为&#xff1a;   第一步&#xff0c;进行系统的可行性分析&#xff0c…

Java 基于微信小程序的校园请教小程序的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

基于单片机手机屏蔽器系统仿真设计

**单片机设计介绍&#xff0c;基于单片机手机屏蔽器系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机手机屏蔽器系统的仿真设计主要涉及到手机信号屏蔽的原理、单片机控制逻辑设计、仿真软件的选择与使用以…

2024北京安全生产展|劳保用品展|安全生产防护用品展会

​作为安全生产与防护用品领域的行业盛会&#xff0c;2024北京安全生产与防护用品展览会将于2024年6月26日至28日在北京.首钢国际会展中心隆重举行。展会紧跟安全生产与防护用品行业发展&#xff0c;充分调研行业需求&#xff0c;以前瞻性的技术研讨、产品展示、产学研对接、需…

VSCode输入花括号{}}会多一个解决方案

打开设置 搜索Closing Brackets 选择BeforeWhitespace 选完后重启下VSCode即可

rust学习(tokio中tcp_stream调用的问题)

问题&#xff1a; 我们涉及了一个socket连接的类&#xff0c;每次收到数据以后&#xff0c;我们都会把tokio::net::TcpStream对应的tcp_stream传递给其他线程。 起初设计如下&#xff1a; pub struct TarNetStream {stream:TcpStream, //1... }pub trait TarListener {fn on…

【C++】类和对象①(什么是面向对象 | 类的定义 | 类的访问限定符及封装 | 类的作用域和实例化 | 类对象的存储方式 | this指针)

目录 前言 什么是面向对象&#xff1f; 类的定义 类的访问限定符及封装 访问限定符 封装 类的作用域 类的实例化 类对象的存储方式 this指针 结语 前言 最早的C版本&#xff08;C with classes&#xff09;中&#xff0c;最先加上的就是类的机制&#xff0c;它构成…

【大数据】大数据概论与Hadoop

目录 1.大数据概述 1.1.大数据的概念 1.2.大数据的应用场景 1.3.大数据的关键技术 1.4.大数据的计算模式 1.5.大数据和云计算的关系 1.6.物联网 2.Hadoop 2.1.核心架构 2.2.版本演进 2.3.生态圈的全量结构 1.大数据概述 1.1.大数据的概念 大数据即字面意思&#x…