【C++】模板类vector的简单实现

news2024/10/1 19:33:21

文章目录

  • 1. 迭代器
  • 2.构造和析构
  • 3. 容量
  • 4. 访问
  • 5.修改
  • 6.测试
  • 完整代码
  • 总结:

在C++的STL库中,vector是一个非常常用的容器,它提供了动态数组的功能。今天我们将一起来实现一个简化版的vector模板类,以便更好地理解它的原理和实现过程。

以下是简化版vector 类的主要实现:

1. 迭代器

vector 的迭代器是一个原生指针,定义如下:

typedef T            value_type;
typedef value_type*  pointer;
typedef value_type*  iterator;
typedef value_type&  reference;

typedef const T*     const_iterator;
typedef const value_type& const_reference;

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

其中,iteratorconst_iterator 分别表示可读写和只读的迭代器,pointerreference 表示指向数据类型的指针和引用。

2.构造和析构

vector 支持默认构造、拷贝构造、赋值操作和析构函数。默认构造函数创建一个空的 vector,而拷贝构造函数将已有的 vector 复制到新的 vector 中。赋值操作符将一个 vector 赋值给另一个 vector

析构函数会释放 vector 占用的内存空间,避免内存泄漏。

T* allocate_and_fill(size_t n, const T& value) {
	T* ptr = new T[n];  // 在动态内存中分配 n 个 T 类型的对象空间
	for (size_t i = 0; i < n; i++) {
		ptr[i] = value;  // 将每个对象初始化为 value
	}
	return ptr;  // 返回指向分配的内存空间的指针
}

void fill_initialize(size_t n, const T& value) {
	_start = allocate_and_fill(n, value);
	_finish = _start + n;
	_endofstorage = _finish;
}

//construct and destroy
vector()	//默认构造
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{}
vector(size_t n, const T& value = T()) {	//构造函数
	fill_initialize(n, value);
}
vector(int n, const T& value = T()) {	//构造函数,加一个int版本以免错误调用下面那个构造
	fill_initialize(n, value);
}
template <class InputIterator>
vector(InputIterator first, InputIterator last) {
	while (first != last) {
		push_back(*first);
		++first;
	}
}
vector(const vector<T>& v) {		//拷贝构造
	//_start = new T[v.capacity()];
	//memcpy(_start, v._start, v.size() * sizeof(T)); //浅拷贝
	//_finish = _start + v.size();
	//_endofstorage = _start + v.capacity();
	reserve(v.capacity());
	for (const auto& e : v) {
		push_back(e);
	}
}
vector<T>& operator= (vector<T> v) {
	swap(v);
	return *this;
}
~vector() {		//析构函数
	if (_start){
		delete[] _start;
		_start = _finish = _endofstorage = nullptr;
	}
}		

3. 容量

vector 的容量包括 sizecapacity。其中 size 表示当前 vector 中元素的个数,而 capacity 表示 vector 内部分配的存储空间的大小。reserve() 函数用于调整 vector 的空间大小,resize() 函数用于调整 vector 的大小。

//capacity
size_t size() const	{
	return _finish - _start;
}
size_t capacity() const {
	return _endofstorage - _start;
}
void reserve(size_t n) {
	if (capacity() < n) {
		const size_t old_size = size(); 
		T* tmp = new T[n];
		if (_start) {
			//memcpy(tmp, _start, n * sizeof(T)); //这是一种浅拷贝
			for (size_t i = 0; i < old_size; i++) {	//进行深拷贝 
				tmp[i] = _start[i];
			}
			delete[] _start;   //1.调用析构函数 2.释放空间
		}
		_start = tmp;
		_finish = _start + old_size;
		_endofstorage = _start + n;
	}
}
void resize(size_t new_size, const T& value = T()) {
	if (new_size > size()) {
		reserve(new_size);
		while (_finish < _start + new_size) {
			*_finish = value;
			++_finish;
		}
	}
	else {
		_finish = _start + new_size;
	}
}

4. 访问

vector 支持随机访问,可以使用下标操作符 [] 来访问 vector 中的元素。同时也提供了 begin()end() 函数来获取迭代器访问 vector 中的元素。

//access
reference operator[](size_t n) {
	return *(begin() + n);
}
const_reference operator[](size_t n) const {
	return *(begin() + n);
}

5.修改

vector 支持在末尾添加元素(push_back()),删除末尾元素(pop_back()),插入元素(insert())和删除元素(erase())等操作。

//modify
void push_back(const T& x) {
	if (_finish == _endofstorage) {
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
	}
	*_finish = x;
	++_finish;
}
void pop_back() {
	assert(size() > 0);
	--_finish;
}
void swap(vector<T>& v) {
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endofstorage, v._endofstorage);
}
iterator insert(iterator pos, const T& x) {
	assert(pos >= _start && pos <= _finish);
	if (_finish == _endofstorage) {
		size_t len = pos - _start;//记录一下_start到pos的距离,以免迭代器失效
		reserve(capacity() == 0 ? 4 : capacity() * 2);
		pos = _start + len;
	}
	//memmove(pos + 1, pos, sizeof(T) * (_finish - pos)); //memove是浅拷贝覆盖
	iterator end = _finish - 1;
	while (end >= pos) {
		(*end + 1) = *end;
		--end;
	}
	*pos = x;

	++_finish;
	return pos;
}
void erase(iterator pos) {
	assert(pos >= _start && pos < _finish);
	iterator it = pos + 1;
	while (it <= _finish) {
		*(it - 1) = *it;
		++it;
	}
	_finish--;
}

6.测试

五个测试函数 test_vector1()test_vector5(),分别测试了 vector 的各种功能。

template <typename T>
void print_vector(const vector<T>& v) {
	for (auto e : v) {
		cout << e << " ";
	}
	cout << endl; 
}


void test_vector1() {
	cout << "test_vector1()" << endl;
	vector<int> v1(10, 1);
	vector<string> v2(10, "asd");
	vector<double> v3(10, 2.3);
	vector<int> v4 = v1;

	print_vector(v1);
	print_vector(v2);
	print_vector(v3);
	v4[6] = 4;
	print_vector(v4);
	cout << v1[6] << endl;
}

void test_vector2() {
	cout << "test_vector1()" << endl;
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	print_vector(v1);
	v1.pop_back();
	v1.pop_back();
	print_vector(v1);
}

void test_vector3() {
	cout << "test_vector1()" << endl;
	vector<int> v;
	v.reserve(10);
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

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

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

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

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

void test_vector4()
{
	cout << "test_vector1()" << endl;
	vector<string> v;
	v.reserve(10);
	v.push_back("xxxx");
	v.push_back("xxxx");
	v.push_back("xxxx");
	v.push_back("xxxx");
	v.push_back("xxxx");
	v.push_back("xxxx");

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

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

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

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

void test_vector5()
{
	cout << "test_vector1()" << endl;
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);

	vector<int> v2(v1.begin(), v1.end());

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

在这里插入图片描述

完整代码

#pragma once
#include <iostream> 
#include <assert.h>
using namespace std;

namespace hd
{
	template<class T>
	class vector
	{
	public:
		//vector 的迭代器是一个原生指针
		typedef T			value_type;
		typedef value_type* pointer;
		typedef value_type* iterator;
		typedef value_type& reference;

		typedef const T* const_iterator;
		typedef const value_type& const_reference;

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

		T* allocate_and_fill(size_t n, const T& value) {
			T* ptr = new T[n];  // 在动态内存中分配 n 个 T 类型的对象空间
			for (size_t i = 0; i < n; i++) {
				ptr[i] = value;  // 将每个对象初始化为 value
			}
			return ptr;  // 返回指向分配的内存空间的指针
		}

		void fill_initialize(size_t n, const T& value) {
			_start = allocate_and_fill(n, value);
			_finish = _start + n;
			_endofstorage = _finish;
		}

		//construct and destroy
		vector()	//默认构造
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}
		vector(size_t n, const T& value = T()) {	//构造函数
			fill_initialize(n, value);
		}
		vector(int n, const T& value = T()) {	//构造函数,加一个int版本以免错误调用下面那个构造
			fill_initialize(n, value);
		}
		template <class InputIterator>
		vector(InputIterator first, InputIterator last) {
			while (first != last) {
				push_back(*first);
				++first;
			}
		}
		vector(const vector<T>& v) {		//拷贝构造
			//_start = new T[v.capacity()];
			//memcpy(_start, v._start, v.size() * sizeof(T)); //浅拷贝
			//_finish = _start + v.size();
			//_endofstorage = _start + v.capacity();
			reserve(v.capacity());
			for (const auto& e : v) {
				push_back(e);
			}
		}
		vector<T>& operator= (vector<T> v) {
			swap(v);
			return *this;
		}
		~vector() {		//析构函数
			if (_start){
				delete[] _start;
				_start = _finish = _endofstorage = nullptr;
			}
		}		
		
		//capacity
		size_t size() const	{
			return _finish - _start;
		}
		size_t capacity() const {
			return _endofstorage - _start;
		}
		void reserve(size_t n) {
			if (capacity() < n) {
				const size_t old_size = size(); 
				T* tmp = new T[n];
				if (_start) {
					//memcpy(tmp, _start, n * sizeof(T)); //这是一种浅拷贝
					for (size_t i = 0; i < old_size; i++) {	//进行深拷贝 
						tmp[i] = _start[i];
					}
					delete[] _start;   //1.调用析构函数 2.释放空间
				}
				_start = tmp;
				_finish = _start + old_size;
				_endofstorage = _start + n;
			}
		}
		void resize(size_t new_size, const T& value = T()) {
			if (new_size > size()) {
				reserve(new_size);
				while (_finish < _start + new_size) {
					*_finish = value;
					++_finish;
				}
			}
			else {
				_finish = _start + new_size;
			}
		}

		//access
		reference operator[](size_t n) {
			return *(begin() + n);
		}
		const_reference operator[](size_t n) const {
			return *(begin() + n);
		}

		//modify
		void push_back(const T& x) {
			if (_finish == _endofstorage) {
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}
			*_finish = x;
			++_finish;
		}
		void pop_back() {
			assert(size() > 0);
			--_finish;
		}
		void swap(vector<T>& v) {
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}
		iterator insert(iterator pos, const T& x) {
			assert(pos >= _start && pos <= _finish);
			if (_finish == _endofstorage) {
				size_t len = pos - _start;//记录一下_start到pos的距离,以免迭代器失效
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}
			//memmove(pos + 1, pos, sizeof(T) * (_finish - pos)); //memove是浅拷贝覆盖
			iterator end = _finish - 1;
			while (end >= pos) {
				(*end + 1) = *end;
				--end;
			}
			*pos = x;
		
			++_finish;
			return pos;
		}
		void erase(iterator pos) {
			assert(pos >= _start && pos < _finish);
			iterator it = pos + 1;
			while (it <= _finish) {
				*(it - 1) = *it;
				++it;
			}
			_finish--;
		}
	private:
		iterator _start;	//指向数据块的开始
		iterator _finish;	//指向有效数据的尾
		iterator _endofstorage;	//指向存储容量的尾
	};

	template <typename T>
	void print_vector(const vector<T>& v) {
		for (auto e : v) {
			cout << e << " ";
		}
		cout << endl; 
	}

	
	void test_vector1() {
		cout << "test_vector1()" << endl;
		vector<int> v1(10, 1);
		vector<string> v2(10, "asd");
		vector<double> v3(10, 2.3);
		vector<int> v4 = v1;

		print_vector(v1);
		print_vector(v2);
		print_vector(v3);
		v4[6] = 4;
		print_vector(v4);
		cout << v1[6] << endl;
	}

	void test_vector2() {
		cout << "test_vector1()" << endl;
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		v1.push_back(6);
		print_vector(v1);
		v1.pop_back();
		v1.pop_back();
		print_vector(v1);
	}

	void test_vector3() {
		cout << "test_vector1()" << endl;
		vector<int> v;
		v.reserve(10);
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		v.push_back(6);

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

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

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

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

	void test_vector4()
	{
		cout << "test_vector1()" << endl;
		vector<string> v;
		v.reserve(10);
		v.push_back("xxxx");
		v.push_back("xxxx");
		v.push_back("xxxx");
		v.push_back("xxxx");
		v.push_back("xxxx");
		v.push_back("xxxx");

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

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

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

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

	void test_vector5()
	{
		cout << "test_vector1()" << endl;
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		v1.push_back(6);

		vector<int> v2(v1.begin(), v1.end());

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

总结:

通过以上的实现和测试,我们可以看到,我们的简化版vector类能够成功地实现动态数组的功能,并且具备了基本的操作和容器相关的函数。当然,这只是一个简化版的实现,与STL库中的vector相比还有很多功能和细节需要进一步完善。
希望本文能够帮助你更好地理解和使用vector容器。如果您对这篇博客内容有任何疑问或建议,欢迎在下方留言进行讨论。

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

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

相关文章

红日靶场2打点记录

因为之前成功用冰蝎免杀360&#xff0c;把权限反弹到了MSF上&#xff0c;然后MSF把权限反弹到CS上 所以这次咱们走捷径直接通过反序列化漏洞连接&#xff08;就是关掉360&#xff09;因为权限弹来弹去感觉好麻烦 提示 大家如果想要免杀360千万别学我&#xff0c;我是之前免杀3…

springboot116基于java的教学辅助平台

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的基于java的教学辅助平台 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四…

前后端分离项目中实现图形验证码

图形验证码在我们的日常生活中时经常用到的&#xff0c;一般用于用户的登录、注册等。 图形验证码在互联网应用中的作用是提高安全性、防止滥用和保护用户隐私。它是一种简单而有效的人机验证技术&#xff0c;帮助保护系统和用户免受自动化攻击的影响。 本次我们通过spring b…

【深度学习每日小知识】NLP 自然语言处理

自然语言处理 (NLP) 是人工智能 (AI) 的一个子领域&#xff0c;处理计算机和人类&#xff08;自然&#xff09;语言之间的交互。它涉及使用算法和统计模型使计算机能够理解、解释和生成人类语言。 NLP 是人工智能领域的重要工具&#xff0c;广泛应用于语言翻译、文本分类和聊天…

短信平台搭建注意什么|网页版短信系统开发源码

短信平台搭建注意什么|网页版短信系统开发源码 短信平台是企业进行市场营销、客户关系管理和即时通讯的重要工具。为了确保短信平台的稳定运行和高效利用&#xff0c;以下是在搭建短信平台时需要注意的几个重要方面。 1. 需求分析&#xff1a;在搭建短信平台之前&#xff0c;需…

Springboot+vue的校园疫情防控系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的校园疫情防控系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的校园疫情防控系统&#xff0c;采用M&#xff…

实时语音克隆,准确复制音色:OpenVoice | 开源日报 No.150

myshell-ai/OpenVoice Stars: 9.6k License: NOASSERTION OpenVoice 是一个通过 MyShell 进行即时语音克隆的开源项目。 OpenVoice 可以准确地克隆参考音色&#xff0c;并生成多种语言和口音的语音。OpenVoice 允许对声音风格进行细粒度控制&#xff0c;如情感、口音以及节奏…

数据库入门:快速了解数据库

目录 序言 一、什么是数据库&#xff1f; 二、DBMS 数据库管理系统&#xff08;DataBase Management System&#xff09; 三、数据库与文件系统的区别 四、数据库的发展和规划 五、常见数据库 5.1 关系型数据库 5.2 非关系型数据库 六、DBMS支持的数据模型 6.1 层次模…

【代码实战】从0到1实现transformer

获取数据 import pathlibimport tensorflow as tf# download dataset provided by Anki: https://www.manythings.org/anki/ text_file tf.keras.utils.get_file(fname"fra-eng.zip",origin"http://storage.googleapis.com/download.tensorflow.org/data/fra-…

Ultimate Crafting System

终极制作系统是您制作游戏的完整解决方案。从流畅的物品和配方创建的基础知识到强大的放置和能量转移系统,它拥有一切。可用于3D和2D游戏。非常适合独立简单的游戏,但程序员可以扩展其终极力量! — 内容 — - 点击式第三人称演示场景 - 第一人称演示场景 - 库存系统 - 从易于…

PIG框架学习3——Redisson 实现业务接口幂等

零、前言 ​ 业务接口幂等问题是在开发中遇到的&#xff0c;如果对业务接口代码不进行幂等控制&#xff0c;并且在前端没有对请求进行限制的情况下&#xff0c;可能会出现多次对接口调用&#xff0c;导致错误异常的发生。就上述情况&#xff0c;对PIGX自带的业务接口幂等实现进…

sql数据库的相关概念与底层介绍

本文中的数据库指的是磁盘数据库。如果有sql语言&#xff08;CRUD&#xff0c;增删改查&#xff09;的使用经验会更容易理解本文的知识点。 数据库与redis的区别 数据库&#xff1a;数据存储长期在磁盘中&#xff0c;小部分频繁需要的数据会被临时提取在内存中。 Redis&…

数组oj 移除元素

思路用双指针更简单&#xff0c;直接用一个数组&#xff0c;开始src和dst都为0&#xff0c;一起往后走(先走dst)&#xff0c;当dst遇到val就停下&#xff0c;src接着走&#xff0c;走到不是val的地方&#xff0c;然后把src赋值给dst&#xff0c;在一起&#xff0c;往后面走。结…

启发式教学是什么

学生们在上课时看似认真听讲&#xff0c;但是在下课后却一片茫然&#xff0c;不知道你讲了什么内容&#xff1f;这是因为你可能使用了传统的教学方法&#xff0c;而不是启发式教学。 启发式教学是指老师在教育教学中&#xff0c;采用引导、启示、激发等手段&#xff0c;调动学…

【操作系统】实验二 Proc文件系统

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

以Python程序为例介绍算法复杂度的估算

文章目录 概念介绍时间复杂度估算空间复杂度估算 引自同一作者百家号文章&#xff1a;「Python语言进阶」算法复杂度是什么&#xff1f;如何估算&#xff1f; 概念介绍 算法&#xff0c;可以理解为解决问题的方法和思路&#xff0c;不是一定得有代码的才叫算法&#xff0c;它…

每日汇评:黄金的市场注意力转向央行和地缘政治

金价从2000美元附近的数周低点反弹&#xff1b; 到目前为止&#xff0c;黄金的进一步巩固当前价格是当前的主题&#xff1b; 地缘政治、宏观数据和央行是本周的主导市场情绪&#xff1b; 黄金价格设法恢复了平衡&#xff0c;扭转了本周开始时的负面走势&#xff0c;从关键争夺区…

AI数据模型支撑下,鼎捷「预测透镜」如何助力汽配厂商浙江华工提质增效?

关于【浙江华工】 浙江华工汽车零部件有限公司&#xff08;以下简称“华工”&#xff09;成立于1987年&#xff0c;位于“中国汽摩配之都”浙江省瑞安塘下镇鲍七工业区&#xff0c;是一家集汽车发动机用冷却水泵和机油泵研发、制造、销售于一体的民营股份制企业。 近些年来&…

六种pdf在线转换工具了解一下-轻松应对pdf转换

PDF文件是我们工作中经常需要使用到的一种文件格式。然而&#xff0c;有时候我们可能需要将PDF文件转换成其他格式以满足特定的需求。为了帮助大家解决这个问题&#xff0c;本文将介绍六种实用的PDF在线转换工具&#xff0c;让你轻松完成各种文件格式的转换。 一、迅捷PDF转换器…

【代码随想录算法训练营第二十四天|回溯算法的理论基础、77. 组合】

代码随想录算法训练营第二十四天|回溯算法的理论基础、77. 组合 回溯算法的理论基础77. 组合 回溯算法的理论基础 这里我觉得《代码随想录》和y总的课都比较好了 《代码随想录》 &#xff1a; https://programmercarl.com/0077.%E7%BB%84%E5%90%88%E4%BC%98%E5%8C%96.html#%E5…