vector的模拟实现

vector介绍:

STL(Standard Template Library)中的vector是一种动态数组容器,可以根据需要自动调整大小。vector可以存储任意类型的数据,并提供了一系列操作函数和方法来访问、插入和删除元素。

vector的模拟实现:

类内成员变量:

在vector中成员变量的类型不像string中的那样,而是泛形类型。

typedef T* iterator;//迭代器
typedef const T* const_iterator;//const类型迭代器

在vector中迭代器的使用是更加频繁的·。迭代器是一个行为类似于指针对象。

private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;

构造函数:

官方实现构造函数的形式有很多种,本文主要实现了三种。

一、

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

二、

将数组内部初始化为相同的内容。在进行实现时选择复用了一些已经写好的函数例如:reverse,push_back。这些函数在本文会一一实现。

vector(size_t n,const T& val = T())
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for(size_t i = 0;0<n;i++)
			{
				push_back(val);
			}

		}
vector(int n, const T& val = T())
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for (size_t i = 0; i < n; i++)
			{
				push_back(val);
			}

		}

三、

利用迭代器进行初始化。我们先来看看官方时如何实现的。

官方在这里用到InputIterator理论上我们可以传任何类型的数据。有时我们想要用第二种方法去初始化时,编译器会使用第三种。

void test4()
	{
		vector<int> v1(5, 0);
		vector<int>::iterator it = v1.begin();
		while(it != v1.end())
		{
			cout << *it;
			it++;
		}
		cout << endl;
	
	}

当我们尝试运行test4时会进行报错。

我的本意是想要通过方法二去对vector进行构造,但是编译器调用的是方法三,因为我们传的是int类型需要进行隐式转换类型编译器会去寻找最适合的。在这里我是直接再加了一个构造函数,新加的构造函数与方法二中的函数的不同点是修改了函数参数,将size_t换成了int。

析构函数

~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

释放空间且将指针置空即可。

拷贝构造

为了防止有vector<vector<int>>等类型的拷贝,我们要在拷贝的时候全部交换,为了防止交换不了的情况我们需要自己写一个交换函数,这个交换函数调用库中的swap函数即可。同时重载=也是要有的,不进行重载的话赋值会有问题。

vector(const vector<T>& val)
		{
			vector<T> tmp(val.begin(), val.end());
			swap(tmp);
		}
		void swap(vector<T>& val)
		{
			std::swap(_start, val._start);
			std::swap(_finish, val._finish);
			std::swap(_end_of_storage, val._end_of_storage);
		}
		vector<T>& operator =(vector<T> val)
		{
			swap(val);
			return *this;
		}

 begin

返回_start。

iterator begin()
	{
		return _start;
	}
const iterator begin()const
	{
		return _start;
	}

end

返回_finish。

iterator end()
	{
		return _finish;
	}
const iterator end()const
	{
		return _finish;
	}

size

返回空间内可存放元素的空间。

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

capacity

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

reserve

扩容函数,如果原先的数组内有内容,我们需要去拷贝。并需要更新_finish,_end_of_storage

void reserve(size_t n)
	{
		if(n>capacity())
		{  
			size_t sz = size();
			T* tmp = new T[n];
			if (_start)
			{
				memcpy(tmp, _start, sizeof(T) * size());
				delete[] _start;
			}
			_start = tmp;
			_finish = _start + sz;
			_end_of_storage = _start+n;
		}
		
	}

resize

当x小于空间大小时删除,大于时扩容并且追加val。

void resize(size_t n, T val = T())
	{
		if (n < size())
		{
			// 删除数据
			_finish = _start + n;
		}
		else
		{
			if (n > capacity())
				reserve(n);

			while (_finish != _start + n)
			{
				*_finish = val;
				++_finish;
			}
		}
	}

empty

判断是否为空,判断start和finish是否相等即可。

bool empty()
	{
		return _start == _finish;
	}

pop_back

尾删,先检查是否为空,若不为空--finish。

void pop_back()
	{
		assert(!empty());
		_finish--;
	}

push_back

void push_back(const T& x)
	{
		if (_finish == _end_of_storage)
		{
			reserve(capacity() == 0 ? 4 : capacity() * 2);
		}

		*_finish = x;
		++_finish;
	}

重载[]

为了方便访问数组内的位置,所以我们需要对[]进行重载,首先检查传入的pos是否大于数组本身的大小,然后返回位置即可。

T& operator [](size_t pos)
	{
		assert(pos < size());
		return *(_start + pos);
	}
	
	const T& operator[](size_t pos)const
	{
		assert(pos < size());
		return *(_start + pos);
	}

insert

insert的实现逻辑并不复杂,但是在进行插入时要注意迭代器失效的问题。尤其是在开辟了新空间之后,将数据复制后要更新迭代器。另外在外部不要调用迭代器。

iterator insert(iterator pos,const T& val)//认为pos失效尽量不要再次调用
	{
		if(_finish == _end_of_storage)
		{
			size_t len = pos - _start;
			reserve(capacity() == 0 ? 4:capacity()*2);
			//更新pos防止迭代器失效
			pos = _start + len;

		}
		iterator end = _finish;
		while(end>=pos)
		{
			*(end + 1) = *end;
			end--;
		}
		*pos = val;
		_finish++;
		return pos;
	}

erase

在删除元素后,不要再使用之前的迭代器,需要重新获取迭代器来指向正确的位置。

iterator erase(iterator pos)//认为pos会失效,不应去访问,原因:行为未定义。指在vs和在g++环境下同样的代码所输出的结果是不同的。
	{
		assert(pos >= _start);
		assert(pos < _finish);
		iterator start = pos + 1;
		while(start != _finish)
		{
			*(start - 1) = *start;
			start++;
		}
		_finish--;
		return pos;

	}

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值