C++--vector的模拟实现

一,引言

vector的模拟实现旨在还原其核心功能,通过深入理解底层架构来提升对标准库vector的掌握程度。vector的实现由类模板实现。其中核心部分是由一个顺序表和三个指针组成:1._start指向顺序表的起始位置2._finish指向有效元素的下一个位置3._end_of_storage指向容器容量的下一个位置迭代器直接使用原生指针表示。首先需要搭建基础框架。如下:

namespace Cao
{
	template <class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

	private:
		iterator _stare = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};
}

其中将vector类包含在Cao的命名空间是为了个标准库中的vector做区分。也可以更好的对比自己写的模拟vector和标准库中给的vector的不同。下文中的所有成员函数都在vector这个类进行实现。接下来还需要写一个打印函数用来呈现模拟vector的运行结果。如下:

template<class T>
void Printf_Container(const vector<T>& v)
{
	auto it = v.begin();
	for (it; it < v.end(); it++)
	{
		std::cout << (*it);
	}
	std::cout << endl;

	for (auto ch : v)
	{
		std::cout << ch << ' ';
	}
	std::cout << endl;
}

打印函数写成模板的形式,可以打印各种数据类型。

二,成员函数

1,size

首先确定元素个数,实现逻辑如下:

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

指针相减返回元素个数。

2,capacity

函数实现vector容器容量的大小,实现逻辑如下:

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

指针相减返回容量大小

3,reserve

对vector容器进行扩容,实现逻辑如下:

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t old_size = size();
		iterator tmp = new T[n];
		for (int i = 0; i < old_size; i++)
		{
			tmp[i] = _str[i];
		}
		delete[]_stare;
		_stare = tmp;
		_finish = _stare + old_size;
		_end_of_storage = _stare + n;
	}
}

当需要扩容的值超过当前 vector 容量时进行扩容,否则无需处理。提前记录 size() 是因为扩容后原内存空间会被释放。最后更新 vector 的三个成员变量。

打印函数和上文的三个函数相对于准备工作。之后就可以插入数据等等一系列函数实现:

4,push_back

在vector数据末尾插入数据。实现如下:

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

首先进行判满,如果满了需要扩容,之后再_finish的位置添加一个元素。

5,pop_back

删除最后一个数据。实现如下:

void pop_back()
{
	_finish--;
}

6,begin,end

返回第一个位置的迭代器,返回最后一个有效元素下一个位置的迭代器。实现如下:

iterator begin()const
{
	return _stare;
}

iterator end()const
{
	return _finish;
}

const_iterator begin()const
{
	return _stare;
}

const_iterator end()const
{
	return _finish;
}

对于const对象要引用const迭代器。否则会引起权限的放大。下文将会仔细写这个问题 。

7,构造函数

构造函数包括三种形式,具体见vector的讲解。实现如下:

第一种默认构造:

vector(const T& val = T())
{
	if (val == T())
	{
		return;
	}
	reserve(1);
	push_back(val);
}

当val传值的时候就开辟一个空间,否则不开空间。

第二种构造:

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

n个val数据的构造。

第三种构造:

template <class inputiterator>
vector(inputiterator first, inputiterator last)
{
	reserve(last - first);
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}

区间构造。注意类模板内部可以进行使用函数模板。

第四种拷贝构造:

vector(const vector<T>& val)
{
	reserve(val.size());
	for (auto& e : val)
	{
		push_back(e);
	}
}

 先经行开辟空间,之后一个一个进行拷贝。

8,swap

交换两个vector对象。具体实现如下:

void swap(vector<T>& v)
		{
			std::swap(_stare, v._stare);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}

交换内部的三个成员变量,底层调用std标准库里面的交换函数。

9,运算符重载(=)

实现赋值操作。具体实现如下:

vector<T>& operator=( vector<T> v)
{
	swap(v);
	return *this;
}

这里的赋值不是传引用传参,所以说形参的改变不影响实参。

10,resize

具体的功能见上文vector解释。具体实现如下:

void resize(size_t n, T val = T())
{
	if (n < size())
	{
		_finish = _stare + n;
	}
	while (n - size())
	{
		push_back(val);
	}
}

size小于n就缩短长度,大于n就指定数值进行填充。 

11,empty

判空,如若返回空就是true,否则是false。具体实现如下:

bool empty()
{
	if (size() == 0)
	{
		return true;
	}
	return false;
}

 

12,运算符重载([])

返回指定位置的引用。具体实现如下:

T& operator[](size_t n)
{
	return _stare[n];
}

const T& operator[](size_t n)const
{
	return _stare[n];
}

第一种可以修改,第二种不可以修改。

13,assign

替换vector对象的数据。具体实现如下:

void assign(size_t n,const  T& val = val())
{
	clear();
	while (n)
	{
		push_back(val);
		n--;
	}
}

 

14,clear

清除vector数据。具体实现如下:

void clear()
{
	_finish = _stare;
}

15,insert

指定位置插入数据。具体实现如下:

iterator insert(iterator pos, const T& x)
{
	// 扩容
	if (_finish == _end_of_storage)
	{
		size_t len = pos - _stare;
		reserve(capacity() == 0 ? 4 : capacity() * 2);
		pos = _stare + len;
	}

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

	++_finish;

	return pos;
}

 主要分为两部分第一部分是判断有没有满。第二部分就移动数据。最后进行插入数据。

三,总结

在进行vector模拟实现中首先是关于权限的问题。加const和不加,有着权限缩小的影响。当用const变量调用非const变量会导致权限放大的错误。第二点关于迭代器失效的问题,下一篇文章会进行详细讲解。第三点是关于reserve深浅拷贝的问题,下一篇文章中也会单独出来讲解。有任何问题可以评论区留言或者私信都会一一解答。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值