STL vector

news2024/9/29 11:31:35

文章目录

  • 一、vector 类的模拟实现

在这里插入图片描述
vector 是一个动态增长的数组,可以存储任意类型

模板参数 T 表示存储元素的类型,Alloc 是空间配置器,一般不用传

vector 的接口使用和 string 类似,参考 string

一、vector 类的模拟实现

vector 类中成员的意义:

  • start:指向动态数组第一个元素
  • finish:指向动态数组最后一个元素的下一个位置
  • end_of_storage:指向动态数组已开辟空间的最后一个空间的下一个位置

在这里插入图片描述

vector 类常用接口模拟实现:

//test.cpp
#include "vector.h"

int main()
{
	starrycat::vector_test4();

	return 0;
}

//vector.h
#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <assert.h>
#include <algorithm>

using std::cout;
using std::endl;

namespace starrycat
{
	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;
		}

		//默认构造函数
		vector<T>()
		{}

		//n 个 value 构造
		//const 引用会延长匿名对象的生命周期
		vector<T>(size_t n, const T& value = T())
		{
			reserve(n);

			for (int i = 0; i < n; ++i)
			{
				start[i] = value;
			}

			finish = start + n;
		}

		//避免内置类型构造时调用迭代器区间构造
		//当第一个参数为整形家族时,需要重载函数
		vector<T>(int n, const T& value = T())
		{
			reserve(n);

			for (int i = 0; i < n; ++i)
			{
				start[i] = value;
			}

			finish = start + n;
		}

		//迭代器区间构造
		template<class InputIterator>
		vector<T>(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		//拷贝构造
		//vector<T>(const vector<T>& v)
		//{
		//	//开空间
		//	reserve(v.capacity());

		//	//深拷贝 vector 数据
		//	for (int i = 0; i < v.size(); ++i)
		//	{
		//		start[i] = v.start[i];
		//	}

		//	finish = start + v.size();
		//	end_of_storage = start + v.capacity();
		//}

		//现代写法
		vector<T>(const vector<T>& v)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}

		//赋值重载
		//vector<T>& operator=(const vector<T>& v)
		//{
		//	if (this != &v)
		//	{
		//		T* tmp = new T[v.capacity() == 0 ? 4 : v.capacity()];

		//		//深拷贝数据
		//		for (int i = 0; i < v.size(); ++i)
		//		{
		//			tmp[i] = v.start[i];
		//		}

		//		delete[] start;
		//		start = tmp;
		//		finish = start + v.size();
		//		end_of_storage = start + v.capacity();
		//	}

		//	return *this;
		//}

		//现代写法
		vector<T>& operator=(vector<T> v)
		{
			swap(v);

			return *this;
		}

		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>()
		{
			delete[] start;
			start = nullptr;
			finish = nullptr;
			end_of_storage = nullptr;
		}

		size_t size() const
		{
			return finish - start;
		}

		size_t capacity() const
		{
			return end_of_storage - start;
		}

		T& operator[](size_t pos)
		{
			assert(pos < size());

			return start[pos];
		}

		const T& operator[](size_t pos) const
		{
			assert(pos < size());

			return start[pos];
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				//深拷贝
				T* tmp = new T[n];
				
				//vector 中如果是自定义类型,也需要深拷贝
				//需要提前保存 sz,否则释放空间后 finish 位置就不对了
				const size_t sz = size();
				for (int i = 0; i < sz; ++i)
				{
					tmp[i] = start[i];
				}

				delete[] start;
				start = tmp;
				finish = start + sz;
				end_of_storage = start + n;
			}
		}

		void resize(size_t n, T value = T())
		{
			if (n < size())
			{
				finish = start + n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}

				while (finish != start + n)
				{
					*finish = value;
					++finish;
				}
			}
		}

		bool empty() const
		{
			return start == finish;
		}

		void push_back(const T& x)
		{
			//扩容
			//if (finish == end_of_storage)
			//{
			//	reserve(capacity() == 0 ? 4 : 2 * capacity());
			//}

			插入数据
			//*finish = x;
			//++finish;

			insert(end(), x);
		}

		void pop_back()
		{
			//assert(!empty());

			//--finish;

			erase(end() - 1);
		}

		iterator insert(iterator pos, const T& value)
		{
			assert(pos <= finish);

			//扩容
			if (finish == end_of_storage)
			{
				//需要更新 pos
				size_t posIndex = pos - start;
				reserve(capacity() == 0 ? 4 : 2 * capacity());
				pos = start + posIndex;
			}

			//移动数据
			iterator cur = end();
			while (cur != pos)
			{
				*cur = *(cur - 1);
				--cur;
			}

			*pos = value;
			++finish;

			return pos;
		}

		void erase(iterator pos)
		{
			assert(pos < finish);

			iterator cur = pos + 1;
			while (cur != end())
			{
				*(cur - 1) = *cur;
				++cur;
			}

			--finish;
		}
		
	private:
		iterator start = nullptr;
		iterator finish = nullptr;
		iterator end_of_storage = nullptr;
	};

	void Print(const vector<int>& v)
	{
		vector<int>::const_iterator it = v.begin();
		while (it != v.end())
		{
			//(*it) *= 2;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (int i = 0; i < v.size(); ++i)
		{
			//v[i] *= 2;
			cout << v[i] << " ";
		}
		cout << endl;
	}

	void vector_test1()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);

		vector<int>::iterator it = v.begin();
		while (it != v.end())
		{
			(*it) *= 10;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		for (int i = 0; i < v.size(); ++i)
		{
			v[i] = i;
			cout << v[i] << " ";
		}
		cout << endl;
		
		Print(v);
	}

	void vector_test2()
	{
		//3 个 1 构造
		vector<int> v1(3, 1);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v2(3);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		//3 个 "111" 构造
		std::string s1 = "111";
		vector<std::string> v3(3, s1);
		for (const std::string& e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<std::string> v4(3);
		for (const std::string& e : v4)
		{
			cout << e << " ";
		}
		cout << endl;

		//3 个 v1 构造
		vector<vector<int>> v5(3, v1);
		for (const vector<int>& e1 : v5)
		{
			for (auto e2 : e1)
			{
				cout << e2 << " ";
			}
			cout << endl;
		}
		cout << endl;

		//迭代器区间构造
		std::string s2 = "abcde";
		vector<int> v6(s2.begin(), s2.end());
		for (auto e : v6)
		{
			cout << e << " ";
		}
		cout << endl;

		int arr[] = { 4, 2, 1, 5, 34, 9 };
		vector<int> v7(arr + 1, arr + sizeof(arr) / sizeof(arr[0]));
		for (auto e : v7)
		{
			cout << e << " ";
		}
		cout << endl;

		//拷贝构造
		vector<int> v8(v7);
		for (auto e : v8)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void vector_test3()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		v.pop_back();
		v.pop_back();
		v.pop_back();
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		v.resize(10, 1);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		v.resize(3);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl << endl;

		vector<std::string> vs;
		vs.push_back("11111");
		vs.push_back("22222");
		vs.push_back("33333");
		vs.push_back("44444");
		vs.push_back("55555");
		for (const std::string& e : vs)
		{
			cout << e << endl;
		}
		cout << endl;

		vs.resize(10, "xxxxx");
		for (const std::string& e : vs)
		{
			cout << e << endl;
		}
		cout << endl;
	}

	void vector_test4()
	{
		vector<int> v;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		//v.push_back(5);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		//如果插入时 vector 扩容了,则迭代器 pos 会失效
		//如果还想使用 pos,则可以接收 insert 返回值
		vector<int>::iterator pos = std::find(v.begin(), v.end(), 2);
		v.insert(pos, 20);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;

		//如果 erase end() - 1 位置的数据,则迭代器失效
		//因此认为 erase(pos) 后,迭代器 pos 失效
		pos = v.end() - 1;
		v.erase(pos);
		for (auto e : v)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

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

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

相关文章

Facebook 已删除 276.7 亿虚假账户,大量真实用户被“误伤”

据Cyber News消息&#xff0c;正有数以千计的用户在X&#xff08;Twitter&#xff09;及其他平台上表达对Facebook的不满&#xff0c;因为该平台在打击虚假账户时对他们的正常账户进行了“误伤”。 自 2017 年 10 月以来&#xff0c;Facebook 已删除了 276.7 亿个虚假账户&…

函数相关概念

4.函数 1.函数的概念 1.什么是函数? 把特点的代码片段,抽取成为独立运行的实体 2.使用函数的好处1.重复使用,提供效率2.提高代码的可读性3.有利用程序的维护 3.函数的分类1.内置函数(系统函数)已经提高的alert(); prompt();confirm();print()document.write(),console.log()…

实训三:多表查询 - 大学数据库创建与查询实战

大学数据库创建与查询实战 第1关&#xff1a;数据库表设计任务描述相关知识大学数据库的整体设计教师信息表&#xff08;instructor&#xff09;开课信息表&#xff08;section&#xff09; 编程要求测试说明参考代码 第2关&#xff1a;查询&#xff08;一&#xff09;任务描述…

【javaweb】学习日记Day10 - tlias智能管理系统 - 部门、员工管理功能开发

目录 一、建立项目的基本操作步骤 二、前期搭建环境 1、创建springboot工程 ​2、引入对应依赖 3、对建立好的框架进行调试 &#xff08;1&#xff09;pom.xml没有显示蓝色怎么解决&#xff1f; &#xff08;2&#xff09; 启动类为橙红色java文件怎么办&#xff1f; 4…

OSS专栏------文件上传(一)

目录 1、简单上传1.1、流式上传1.1.1、上传字符串1.1.1.1、代码示例1.1.1.2、执行结果 1.1.2、上传Byte数组1.1.2.1、代码示例1.1.2.2、执行结果 1.1.3、上传网络流1.1.3.1、代码示例1.1.3.2、执行结果 1.1.4、上传文件流1.1.4.1、代码示例1.1.4.2、执行结果 1.2、文件上传1.2.…

申威芯片UOS中opencv DNN推理

Cmake&#xff0c;opencv&#xff0c;opencv-contribute安装 #apt可能需要更新apt update apt install -y wget unzip apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev#安装cmake apt i…

【OceanBase概念】国产数据库OceanBase的那些事儿(1)初识OceanBase

文章目录 写在前面涉及知识点1、OceanBase是什么&#xff1f;1.1基本概念1.2发展历史 2、TPC-C认证2.1什么是TPCC2.2OceanBase认证成果 3、OceanBase应用场景3.1行业应用A、金融行业B、电信运营行业C、保险行业D、初创互联网行业 3.2内部应用A、支付宝B、淘宝C、网商银行D、Pay…

草图大师SketchUp Pro 2023 for Mac

SketchUp Pro 2023 for Mac&#xff08;草图大师&#xff09;是一款专业的三维建模软件&#xff0c;由Trimble Inc.开发。它可以用于创建、修改和分享3D模型&#xff0c;包括建筑、家具、景观等。 SketchUp Pro 2023 for Mac提供了简单易学的用户界面和强大的工具集&#xff0…

【数据恢复】.360勒索病毒|金蝶、用友、OA、ERP等软件数据库恢复

引言&#xff1a; 在当今数字化的时代&#xff0c;网络犯罪已经演变成了一场全球性的威胁&#xff0c;而 360 勒索病毒则是其中最为可怕和具有破坏性的威胁之一。这种恶意软件以其危害深远、难以防范的特点而令人震惊。本文91数据恢复将深入探讨 360 勒索病毒的可怕性&#xff…

Navicat连接mysql8.0:提示无法加载身份验证插件“caching_sha2_password”

Navicat连接mysql时&#xff0c;提示&#xff1a;Unable to load authentication plugin ‘caching_sha2_password‘. 原因&#xff1a;mysql 8.0 默认使用 caching_sha2_password 身份验证机制。 D:\MySQL8.0\install\bin>mysql -uroot -p123456789 #登录 mysql: [War…

【Redis】Redis 通用命令、键的过期策略

文章目录 一、基础命令SET 和 GET 二、全局命令KEYSEXISTSDELEXPIRE 和 TTL经典面试题&#xff1a;Redis 中 key 的过期策略是怎么实现的TYPE Redis 有许多种数据结构&#xff0c;但是这些数据结构的 key 的类型都是字符串类型的&#xff08;所以说&#xff0c;Redis 不同的数据…

vue插槽slot

插槽有三种&#xff1a; 目录 1.普通插槽 2.具名插槽 3.作用域插槽 1.普通插槽 sub.vue 子组件 --- 子组件写slot标签&#xff0c;父组件的Sub标签内填写的内容会显示在slot的位置&#xff0c;父组件如果不写内容就会展示默认内容。 <template><div class"…

智慧物流发展的重要推动力量:北斗卫星导航系统

随着经济的快速发展和电商的普及&#xff0c;物流行业的规模不断扩大&#xff0c;对物流运输的效率和安全性也提出了更高的要求。传统的物流运输方式存在着效率低下、信息不对称、安全隐患等问题&#xff0c;因此发展智慧物流已经成为物流行业的必然趋势。智慧物流可以通过先进…

软文发稿平台那么多,为什么选择媒介盒子

近年来随着互联网技术的发展&#xff0c;越来越多的企业开始注重软文营销&#xff0c;品牌软文推广对企业来说是至关重要的&#xff0c;也有许多企业选择和软文发稿平台合作来增强品牌曝光&#xff0c;提升宣传效果&#xff0c;那么为什么会有这么多企业选择媒介盒子合作呢&…

2023高教社杯 国赛数学建模A题思路 - 定日镜场的优化设计

1 赛题 A 题 定日镜场的优化设计 构建以新能源为主体的新型电力系统&#xff0c; 是我国实现“碳达峰”“碳中和”目标的一项重要 措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。 定日镜是塔式太阳能光热发电站(以下简称塔式电站)收集太阳能的基本组件&…

微服务04-Gateway网关

作用 身份认证&#xff1a;用户能不能访问 服务路由&#xff1a;用户访问到那个服务中去 负载均衡&#xff1a;一个服务可能有多个实例&#xff0c;甚至集群&#xff0c;负载均衡就是你的请求到哪一个实例上去 请求限流功能&#xff1a;对请求进行流量限制&#xff0c;对服务…

【智慧工地源码】物联网和传感器技术在智慧工地的应用

物联网&#xff08;IoT&#xff09;和传感器技术在智慧工地中扮演着至关重要的角色。这些技术的应用&#xff0c;使得智慧工地能够实现对施工过程的精确监控、数据收集和分析&#xff0c;以及设备互联&#xff0c;从而提高工程效率、减少成本并改善工人的工作环境。 一、物联网…

Faster RCNN

【简介】 Faster RCNN[7]是第一个端到端&#xff0c;最接近于实时性能的深度学习检测算法&#xff0c;该网络的主要创新点就是提出了区域选择网络用于申城候选框&#xff0c;能几大提升检测框的生成速度。该网络首先输入图像到卷积网络中&#xff0c;生成该图像的特征映射。在特…

cocos 之纹理格式和压缩纹理

Cocos2dx 版本&#xff1a; 3.10 CocosCreator 版本&#xff1a; 3.8.0 环境&#xff1a; Mac 简介 在项目开发中&#xff0c;图片资源的优化是作为性能优化和包体优化的一项重要侧露。常用的手段有&#xff1a; 使用TexturePacker将散图打包图集 JPG和PNG的使用&#xff0…

SpringMVC概述,SpringMVC是什么,有什么优势?

目录 一、MVC 模式 二、SpringMVC 是什么&#xff1f; 三、SpringMVC的优势 四、SpringMVC 的应用场景 一、MVC 模式 MVC模式是一种软件架构模式&#xff0c;它将软件的用户界面&#xff08;即前台页面&#xff09;和业务逻辑分离&#xff0c;使代码具有更高的可扩展性、可…