【STL】:vector的模拟实现

这篇具有很好参考价值的文章主要介绍了【STL】:vector的模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关vector的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

目录

1. 基本构造

2. 容量相关的接口

2.1 operator[ ]

2.2 reserve

2.3 resize

2.4 size、capacity

3. 迭代器

4. 修改相关接口

4.1 insert、push_back

4.2 erase

5. 拷贝构造和赋值重载和其他构造

5.1 拷贝构造

5.2 赋值重载

5.3 其他构造

6. 完整代码


1. 基本构造

在实现vector之前可以先看一下库里面的vector是如何实现的:

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

#pragma once
#include <assert.h>

namespace ywh
{
	template<class T>
	class vector
	{
		typedef T* iterator;
		typedef const T* const_iterator;
	public:
		/基本构造///
		//构造
		vector()
		{}
		//析构
		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}
	private:
		iterator _start = nullptr;   //起始
		iterator _finish = nullptr;  //有效数据个数
		iterator _end_of_storage = nullptr; //有效空间
	};
}

2. 容量相关的接口

2.1 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];
		}

2.2 reserve

关于reserve的实现最主要的就是深拷贝与浅拷贝的问题,使用浅拷贝对于内置类型很容易处理,但是对于自定义类型就会出现麻烦:

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

需要进行深拷贝,关于自定义类型的赋值重载就是一个深拷贝,所以我们需要使用深拷贝来说实现reserve:

//reserve
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//浅拷贝
					//对于自定义类型不能处理
					//memcpy(tmp,_start,sizeof(T)*sz);
					//采用深拷贝
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}	
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;
			}
		}

2.3 resize

//resize
		//这里使用匿名对象进行缺省值的传参,由于匿名函数具有常性所以要使用const
		void resize(size_t n, const T& val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

2.4 size、capacity

有效元素的个数从开始位置到数据截止位置

容量是开始位置到空间终止位置

//容量
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}
		//有效个数
		size_t size() const
		{
			return _finish - _start;
		}

3. 迭代器

关于模拟实现的vector只实现正向迭代器,反向迭代器的实现会在stack和queue的适配器模式中详解

/迭代器
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}

4. 修改相关接口

4.1 insert、push_back

在insert的时候需要注意的是:假如需要扩容,那么pos还是在旧空间,所以在扩容之前需要将旧空间pos的偏移量记录出来,然后在扩容之后将新空间的pos记录出来。

//在pos位置插入
		void insert(iterator pos, const T& x)
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _end_of_storage)
			{
				//记录旧空间中pos的偏移量
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				//找出新空间的pos
				pos = _start + len;
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;
		}
		//尾插
		void push_back(const T& x)
		{
			//复用插入
			insert(end(), x);
		}

insert之后的迭代器会失效,上述中的pos就是迭代器失效的一种案例,在不同的平台下对于迭代器的失效都有不同的检查方法,VS2019上如果使用insert之后的迭代器是不允许进行使用的。

4.2 erase

	//删除pos位置
		void erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);
			
			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
		}

如果我们单纯的看这个代码会感觉erase之后迭代器是不会失效的,但是erase之后迭代器失效会在特殊情况下展示出来,比如要删除偶数:

void Test()
{
	ywh::vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	ywh::vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
        //删除偶数
		if (*it % 2 == 0)
		{
			v.erase(it);
		}
		it++;
	}

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

在这里有三种情况:

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

我们可以看看库里面是如何设计的:

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

对于返回值的介绍:

返回被删除数据的下一个位置

【STL】:vector的模拟实现,C++,c++,开发语言,stl,vector

所以我们需要对我们实现的erase进行调整:

//删除pos位置
		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);
			
			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			//返回删除位置的后一个位置
			return pos;
		}
void Test()
{
	ywh::vector<int> v;
	v.push_back(2);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);
	v.push_back(5);
	v.push_back(6);

	ywh::vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		if (*it % 2 == 0)
		{
			//删除后自动找到删除位置的下一个位置
			v.erase(it);
		}
		else
		{
			//不符合情况再往后面走
			it++;
		}
	}

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

5. 拷贝构造和赋值重载和其他构造

5.1 拷贝构造

//拷贝构造
		vector(const vector<T>& v)
		{
            //开辟空间
			reserve(v.capacity());
            //依次尾插
			for (auto e : v)
			{
				push_back(e);
			}
		}

5.2 赋值重载

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> tmp) 
{
	//直接交换
	swap(tmp);
	return *this;
}

5.3 其他构造

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

		//n个val构造
		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				//n个val进行尾插
				push_back(val);
			}
		}
		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				//n个val进行尾插
				push_back(val);
			}
		}

6. 完整代码

头文件:Vector.h

#pragma once
#include <assert.h>

namespace ywh
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
	public:
		/迭代器
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}

		/基本构造///
		//构造
		vector()
		{}

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

		//n个val构造
		vector(size_t n, const T& val = T())
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				//n个val进行尾插
				push_back(val);
			}
		}
		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; i++)
			{
				//n个val进行尾插
				push_back(val);
			}
		}

		//拷贝构造
		vector(const vector<T>& v)
		{
			//开辟空间
			reserve(v.capacity());
			//依次尾插
			for (auto e : v)
			{
				push_back(e);
			}
		}


		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}
        //operator=
		vector<T>& operator=(vector<T> tmp) 
		{
			//直接交换
			swap(tmp);
			return *this;
		}

		//析构
		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}
		///容量
		//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];
		}
		//容量
		size_t capacity() const
		{
			return _end_of_storage - _start;
		}
		//有效个数
		size_t size() const
		{
			return _finish - _start;
		}
		//reserve
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//浅拷贝
					//对于自定义类型不能处理
					//memcpy(tmp,_start,sizeof(T)*sz);
					//采用深拷贝
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}	
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;
			}
		}
		//resize
		//这里使用匿名对象进行缺省值的传参,由于匿名函数具有常性所以要使用const
		void resize(size_t n, const T& val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				reserve(n);
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		///修改
		//在pos位置插入
		void insert(iterator pos, const T& x)
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			if (_finish == _end_of_storage)
			{
				//记录旧空间中pos的偏移量
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				//找出新空间的pos
				pos = _start + len;
			}
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = x;
			++_finish;
		}
		//尾插
		void push_back(const T& x)
		{
			//复用插入
			insert(end(), x);
		}
		//删除pos位置
		iterator erase(iterator pos)
		{
			assert(pos >= _start);
			assert(pos < _finish);
			
			iterator it = pos + 1;
			while (it < _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			//返回删除位置的后一个位置
			return pos;
		}

	private:
		iterator _start = nullptr;   //起始位置
		iterator _finish = nullptr;  //有效数据位置
		iterator _end_of_storage = nullptr; //结束位置
	};
}

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持! 文章来源地址https://www.toymoban.com/news/detail-742028.html

到了这里,关于【STL】:vector的模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • C++ STL vector 模拟实现

    C++ STL vector 模拟实现

    ✅1主页:我的代码爱吃辣 📃2知识讲解:C++之STL 🔥3创作者:我的代码爱吃辣 ☂️4开发环境:Visual Studio 2022 💬5前言:上次我们已经数字会用了vector,这次我们对其底层更深一步挖掘,其中重点是,Vector中一些深浅拷贝问题。 目录 一.Vector模拟实现的整体框架 二. Vector的构

    2024年02月13日
    浏览(14)
  • 【C++ STL】vector模拟实现

    【C++ STL】vector模拟实现

    2023年05月17日
    浏览(27)
  • C++ [STL之vector模拟实现]

    C++ [STL之vector模拟实现]

    本文已收录至《C++语言》专栏! 作者:ARMCSKGT vector是STL容器容器之一,其底层实现类似于数据结构顺序表,相当于string来说得益于泛型模板的加持使得vector可以变为任何类型,且是可以动态扩容,堪称大号数组!在vector的实现中,有许多值得我们学习的细节,接下来将为大家

    2024年02月11日
    浏览(6)
  • C++ —— STL容器【vector】模拟实现

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

    本章代码gitee仓库:vector模拟实现、vector源码 看源码发现 vector 是类模板定义的,成员是采用迭代器进行管理 当涉及到容器类时,通常有一些关键函数,如构造函数、析构函数和拷贝构造函数,它们负责初始化容器对象、销毁对象和进行对象的拷贝等 这里注意拷贝构造要实现

    2024年02月16日
    浏览(8)
  • 【C++】STL 模拟实现之 vector

    【C++】STL 模拟实现之 vector

    vector 是我们学习的第一个真正的 STL 容器,它接口的使用方式和 string 有一点点的不同,但大部分都是一样的,所以这里我们就只演示其中一些接口的使用,大家如果有疑惑的地方直接在 cplusplus 是上面查看对应的文档即可。 vector 提供了四种构造方式 – 无参构造、n 个 val 构

    2023年04月27日
    浏览(10)
  • 【C++STL】模拟实现vector容器

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

    本文带你进入vector的模拟实现,对于vector,是我们深入学习STL的必要途径。 根据库的实现方式,成员函数如下: c++11开始可以对成员变量使用缺省值,在这里我们可以使用缺省值。 size的大小为_finish - _start capacity的大小为_end_of_storage - _start 该函数的作用是:扩容。 思路:

    2024年02月16日
    浏览(5)
  • STL 关于vector的细节,vector模拟实现【C++】

    STL 关于vector的细节,vector模拟实现【C++】

    _start指向容器的头,_finish指向容器当中 有效数据 的下一个位置,_endofstorage指向整个容器的尾 先开辟一块与该容器大小相同的空间,然后将该容器当中的数据一个个拷贝过来即可,最后更新_finish和_endofstorage的值即可。 深拷贝版本一: 注意: 不能使用memcpy函数 , 如果vec

    2024年02月15日
    浏览(9)
  • 【C++STL】“vector“容器的模拟实现

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

    🎉博客主页:小智_x0___0x_ 🎉欢迎关注:👍点赞🙌收藏✍️留言 🎉系列专栏:C++初阶 🎉代码仓库:小智的代码仓库 这里的 iterator 是 typedef T* iterator; 定义来的, T 是模板参数。 _start 是指向开始的指针变量。 _finish 是指向最后一个元素的下一位的指针变量。 _endofstorage 是

    2024年02月16日
    浏览(7)
  • 【STL模版库】模拟实现vector类模版

    【STL模版库】模拟实现vector类模版

    解释: [1] 对于顺序表迭代器就是指向其内部元素的指针。 [2] 下面是其结构示意图: 解释: [1] 构造函数必须要先将3个迭代器置空,否则在reserve开空间时会出现访问野指针的问题。 [2] 第二个参数用T类型的匿名对象做缺省值,相当于去调默认构造。生成的匿名对象具有常性

    2024年02月06日
    浏览(6)
  • 【c++】:STL中vector的模拟使用及模拟实现

    【c++】:STL中vector的模拟使用及模拟实现

        文章目录 前言 一.使用库中vector常用接口 二.vector的模拟实现 总结   上一篇我们讲解了STL中的string的使用和模拟实现,这次我们就来讲解STL中的vector,vector相对于string来说模拟实现会难一些,难点在于迭代器失效问题和深浅拷贝问题。 首先介绍一下vector: 1. vector是表示

    2024年01月21日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包