C++ —— STL容器【vector】模拟实现

news2024/11/18 1:51:48

在这里插入图片描述

本章代码gitee仓库:vector模拟实现、vector源码

文章目录

  • 😈0. 搭个框架
  • 😄1. 成员
  • 👻2. 构造函数 & 析构函数 & 拷贝构造
  • 😺3. 迭代器
  • 🙉4. operator[] & operator=
  • 🤖5. 容器的容量 & 个数
  • 👾6. 扩容
  • 👿7. 插入 & 删除操作

😈0. 搭个框架

#include<iostream>
#include<vector>
#include<string>
#include<assert.h>
using std::cout;
using std::endl;
namespace myvector
{
	template<typename T>
	class vector
    {
        public:
        	typedef T* iterator;
        	typedef const T* const_iterator;
        private:
    }
    
    //代码测试区
    void t1(){}
    //...
}

😄1. 成员

看源码发现vector是类模板定义的,成员是采用迭代器进行管理

image-20230725211854440

iterator _start;	//初始位置
iterator _finish;	//结束位置
iterator _end_of_storage;	//容量

👻2. 构造函数 & 析构函数 & 拷贝构造

当涉及到容器类时,通常有一些关键函数,如构造函数、析构函数和拷贝构造函数,它们负责初始化容器对象、销毁对象和进行对象的拷贝等

这里注意拷贝构造要实现的是深拷贝

vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}

vector(size_t n, const T& val=T())
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	resize(n, val);
}
//有选择
vector(int n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	resize(n, val);
}

//拷贝构造
vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	size_t vSize = v.size();
	if (vSize > 0)
	{
		_start = new T[vSize];
        //深拷贝
		for (size_t i = 0; i < vSize; i++)
		{
			_start[i] = v._start[i];
		}
		_finish = _start + vSize;
		_end_of_storage = _start + vSize;
	}
}
//迭代器初始化
template<typename InpuIterator>
vector(InpuIterator first, InpuIterator last)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
//析构
~vector()
{
	if (_start)
	{
		delete[] _start;
		_start = _finish = _end_of_storage = nullptr;
	}
}

😺3. 迭代器

加上const,兼容具有常属性的元素

iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}
const const_iterator begin() const
{
	return _start;
}
const const_iterator end() const
{
	return _finish;
}

🙉4. operator[] & operator=

重载[]操作符,下标访问,方便查看
重载=操作符,用于将当前容器对象赋值为另一个容器对象

当执行容器的深拷贝时(例如使用赋值运算符 =),会创建一个新的独立的容器,并复制原始容器的元素到新容器中。
在深拷贝过程中,原始容器和新容器中的元素是独立的,它们有各自的内存空间。
深拷贝可以防止两个容器共享相同的元素内存,从而避免了一个容器修改元素影响另一个容器的问题。

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 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>& operator=(vector<T> v)
{
	swap(v);
	return *this;
}

🤖5. 容器的容量 & 个数

size_t capacity() const
{
	return _end_of_storage - begin();
}
size_t size() const
{
	return _finish - _start;
}

👾6. 扩容

void reserve(size_t n)
{
	if (capacity() < n)
	{
		const size_t old_size = size();
		iterator tmp = new T[n];
		//	_start不为空挪数据
		if (_start)
		{
            //实现深拷贝
            //memcpy(tmp, _start, sizeof(T) * old_size);
			for (size_t i = 0; i < old_size; ++i)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}
		_start = tmp;
		_finish = tmp + old_size;
		_end_of_storage = _start + n;
	}
}

void resize(size_t new_size, const T& x = T())
{
	if (new_size < size())
		_finish = _start + new_size;
	else
	{
		reserve(new_size);
		while (_finish != _start + new_size)
		{
			*_finish = x;
			++_finish;
		}
	}
}

👿7. 插入 & 删除操作

指定位置插入/删除时,要注意迭代器失效的问题,采用iterator为返回类型,可以接收修改后的位置

迭代器失效:
在对容器进行插入和删除操作时,特别是涉及重新分配内存的情况下,会导致迭代器失效。
插入元素可能导致插入位置之后的元素迭代器失效,而删除元素可能导致删除位置之后的元素迭代器失效。
一旦迭代器失效,对其进行解引用或使用会导致未定义的行为

void push_back(const T& x)
{
	insert(end(), x);
	/*if (_finish == _end_of_storage)
	{
		reserve(capacity() == 0 ? 4 : 2 * capacity());
	}
	*_finish = x;
	_finish++;*/
}
void pop_back()
{
	--_finish;
}
iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);
	if (_finish == _end_of_storage)
	{
		size_t n = pos - begin();
		reserve(capacity() == 0 ? 4 : 2 * capacity());
		pos = begin() + n;
	}
	iterator end = _finish - 1;
	while (pos <= end)
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = x;
	++_finish;
	return pos;
}
iterator erase(iterator pos)
{
	assert(pos >= _start && pos < _finish);
	if (pos+1 != _finish)
	{
		iterator it = pos + 1;
		while (it != _finish)
		{
			*(it-1) = *it;
			++it;
		}
	}
	--_finish;
	return pos;
}

这里还是要注意深浅拷贝,自定义类型一定是要进行深拷贝的。

那么本期的分享就到这里,我们下期再见,如果还有下期的话。

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

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

相关文章

Vue mixin 混入

可以复用的组件&#xff0c;我们一般会抽离&#xff0c;写成公共的模块。 可以复用的方法&#xff0c;我们一般会抽离&#xff0c;写成公共的函数。 那么 在 Vue 中&#xff0c;如果 某几个组件实例 VueComponent 中、或者 整个 Vue 项目中 都存在相同的配置&#xff0c;那就…

jmeter-断言

断言作用&#xff1a;让脚本自动化执行过程中&#xff0c;能够自动判定执行结果是否正确&#xff0c;需要添加断言 响应断言 添加方式&#xff1a;测试计划–》线程组–》HTTP请求–》(右键添加)断言–》响应断言 案例 请求:https://www.baidu.com 检查&#xff1a;让程序检查…

13.4 【Linux】使用者身份切换

使用一般帐号&#xff1a;系统平日操作的好习惯 尽量以一般身份使用者来操作Linux的日常作业。等到需要设置系统环境时&#xff0c; 才变换身份成为 root 来进行系统管理&#xff0c;相对比较安全。避免作错一些严重的指令&#xff0c;例如恐怖的“ rm -rf / ”。 用较低权限…

OpenTDF数据加密引擎

OpenTDF是Virtru公司的开源项目。 Virtru基于OpenTDF开发了用于google Workspace和Microsoft 365的相关数据安全产品。 简介 virtru公司基于opentdf开发挺多产品的,都是数据安全类产品。 能把opentdf开源,已经非常不容易了。 opentdf的代码看起来还是比较整齐和成熟的。…

flink写入到kafka 大坑解析。

1.kafka能不能发送null消息&#xff1f; 能&#xff01; 2 flink能不能发送null消息到kafka&#xff1f; 不能&#xff01; public static void main(String[] args) throws Exception {StreamExecutionEnvironment env StreamExecutionEnvironment.getExecutionEnvironment(…

mysql 第九章

目录 1.mha 搭建 2.总结 1.mha 搭建 主从同步&#xff1a; 安装 mha 软件&#xff1a; mha 模拟 vip 飘移、master 切换&#xff1a; 2.总结 mha 是一套优秀的 mysql 高可用环境下故障切换和主从复制的软件。mha 解决 mysql 单点的问题。mysql 故障切换过程中&#xff0c;mh…

Linux 学习记录57(ARM篇)

Linux 学习记录57(ARM篇) 本文目录 Linux 学习记录57(ARM篇)一、外部中断1. 概念2. 流程图框 二、相关寄存器1. GIC CPU Interface (GICC)2. GIC distributor (GICD)3. EXTI registers 三、EXTI 寄存器1. 概述2. 内部框图3. 寄存器功能描述4. EXTI选择框图5. EXTI_EXTICR1 &…

Qt Creator mainwindow.obj:-1: error: LNK2019

构建的时候报错&#xff1a; mainwindow.obj:-1: error: LNK2019: 无法解析的外部符号 "public: __thiscall mynotedig::mynotedig(class QWidget *)" (??0mynotedigQAEPAVQWidgetZ)&#xff0c;该符号在函数 "public: void __thiscall MainWindow::mynoteab…

C语言宏替换的注意事项

先思考一个问题&#xff1a; #include <string> #include <Windows.h>namespace ui { int MessageBox(HWND hwnd, const std::wstring &text, const std::wstring &caption,UINT flags) {UINT actual_flags flags;const wchar_t *text_ptr text.c_str();…

推荐 3 个实用的 GitHub 项目

本期推荐开源项目目录&#xff1a; 1. 开源知识库 2. 去中心化的社交平台 3. h2oGPT 01 开源知识库 AFFINE 是 Notion、Miro 等知识库产品的开源替代品&#xff0c;目前已经获得了近 20k 的 Stark。通过 AFFINE 你可以进行写作、绘画、计划管理。 类似于 Notion 的 Block &…

STC12C5A系列单片机片内看门狗的应用

wdt.c #include "wdt.h"void wdt_init(void) {WDT_CONTR 0x24; // 0010 0100 - 1.1377s }void wdt_feed(void) {WDT_CONTR | 0x10; // 喂狗 }wdt.h #ifndef _WDT_H_ #define _WDT_H_#include "stc12c5a60s2.h"// 函数声明 extern void wdt_init(void); …

Ajax 黑马学习

Ajax 资源 数据是服务器对外提供的资源,通过 请求 - 处理 - 响应方式获取 请求服务器数据, 用到 XMLHttpRequest 对象 XMLHttpRequest 是浏览器提供的js成员, 通过它可以请求服务器上的数据资源 let xmlHttpRequest new XMLHttpRequest(); 请求方式 : get向服务器获取数据…

requests---jsonpath在接口自动化中的应用

前言 我们在做接口测试时&#xff0c;大多数返回的都是json属性&#xff0c;我们需要通过接口返回的json提取出来对应的值&#xff0c;然后进行做断言或者提取想要的值供下一个接口进行使用&#xff0c;但是如果返回的json数据嵌套了很多层&#xff0c;通过查找需要的词&#x…

软件进行用户体验测试有哪些要点?

无论是移动应用还是网页应用&#xff0c;优秀的用户体验是软件成功的关键所在。软件用户体验测试是一种关键的测试方法&#xff0c;旨在评估用户在使用软件过程中的感受和体验。通过深入了解用户需求&#xff0c;模拟真实场景&#xff0c;以及综合用户反馈&#xff0c;软件开发…

【C++】C++11——右值引用和移动语义|可变参数模板

文章目录 一、左值引用和右值引用左值引用和右值引用的定义左值引用和右值引用的比较 二、右值引用的使用场景和意义左值引用的短板移动构造和移动赋值万能引用和完美转发 三、新的类功能类成员变量初始化default 和 delete 四、可变参数模板 一、左值引用和右值引用 传统的C语…

操作系统资源限制问题(Memory Analyzer使用OutOfMemoryError)

java8使用Memory Analyzer大概是10左右的版本&#xff0c;用最新版本要java17 MemoryAnalyzer-1.10.0.20200225-win32.win32.x86_64 MAT(Memory Analyzer Tool)下载 https://www.cnblogs.com/zwh0910/p/15774590.html Eclipse downloads - Select a mirror | The Eclipse F…

"科技与狠活"企业级无代码开发MES系统,一周实现数字化

随着科技的不断发展&#xff0c;企业级无代码开发平台成为了一种新型的解决方案&#xff0c;能够有效降低软件开发门槛&#xff0c;提升开发效率。在制造业领域&#xff0c;MES系统&#xff08;Manufacturing Execution System&#xff09;作为一种关键的生产管理工具&#xff…

小程序开发收费多少

一、小程序开发费用一览表 ① 域名费用 域名的价格取决于选择的域名类型&#xff0c;常见的有如.com、.cn等这些&#xff0c;以及注册商的定价策略。比如&#xff0c;一个.com 域名一年的的注册费用大约在 50-200 元人民币之间。 ②服务器费用 服务器费用是根据服务器的配置…

day37-Pokedex(神奇宝贝图鉴卡牌展示)

50 天学习 50 个项目 - HTMLCSS and JavaScript day37-Pokedex&#xff08;神奇宝贝图鉴卡牌展示&#xff09; 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&qu…

vscode默认gbk编码格式打开

目录 1. 问题描述2. 解决方案 1. 问题描述 每次打开vscode都是utf-8格式打开文件&#xff0c;然后满屏的中文乱码&#xff0c;自己手动换成gbk编码 后中文显示正常&#xff0c;但是换多了很烦。 2. 解决方案 ctrlshiftP 点首选项&#xff1a;打开用户设置 加上这行在最后&…