STL--vector模拟实现

一、前言

在另一篇博客中我已经写了:vector容器介绍和使用以及迭代器失效问题,那么在这篇博客中我将要模拟实现一个简单的vector,对vector实现基本的增、删、改。

下图是vector的基本结构:

STL--vector模拟实现_第1张图片

二、vector的成员、构造、析构、迭代器的基本实现

#pragma once
#include
#include

namespace Myvector{
     
	template<class T>
	class vector {
     
	public:
		//因为vector的底层是连续的,所以可以使用原生指针来当作迭代器使用
		typedef T* iterator;	
		typedef const T* const_iterator;	//const引用const迭代器
		
		iterator begin() {
     
			return _start;
		}
		iterator end() {
     
			return _finish;
		}

		const_iterator begin() const{
     
			return _start;
		}

		const_iterator end() const{
     
			return _finish;
		}
		//当前vector元素的有效个数
		size_t size(){
     
			return _finish - _start;
		}
		//当前vector容器的个数
		size_t capacity() {
     
			return end_of_storage - _start;
		}
		
		//构造函数,构造一个空的vector
		vector():
		_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
		{
     }
		
		//vector的析构函数
		~vector() {
     
			delete[]_start;
			_start = _finish = end_of_storage = nullptr;
		}
		
	private:
		iterator _start;
		iterator _finish;
		iterator end_of_storage;
	}
}

三、check_capacity、reserve方法

STL--vector模拟实现_第2张图片

3.1 check_capacity判断是否达到扩容条件

	void check_capacity() {
     
		if (_finish == end_of_storage) {
     
			size_t newcapacity = capacity() == 0 ? 1 : 2 * capacity();//当最初的时候,容量为0,要给个初始值
			reserve(newcapacity);
		}
	}

3.2 reserve实现重新配置、元素移动、释放原空间

	void reserve(size_t n) {
     
		if (n > capacity()) {
     
			size_t sz = size();	//保存原有vector的大小
			T* tmp = new T[n];	//重新配置新空间
			//	memcpy(tmp,_start,sizeof(T)*size()); 出现深浅拷贝问题
			for(size_t i=0;i<sz;i++){
     
				tmp[i] = _start[i];
			}
			
			delete[] _start;	//释放原空间
			
			//将vector的指针指向新配置的空间
			_start = tmp;		
			_finish = _start + sz;
			end_of_storage = _start + n;
		}
	}

4.1 分析使用memcpy进行拷贝会出现什么问题

int main()
{
     
	Myvector::vector<string> v;
	v.push_back("1111");
	v.push_back("2222");
	v.push_back("3333");
	return 0;
}

问题分析:

■ 1、memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中。

■ 2、如果拷贝的是自定义类型的元素,memcpy高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型中涉及到资源管理,就会出错,因为memcpy的拷贝实际是浅拷贝,当释放掉原来的空间时,那么我们重新分配的空间将指向野指针。

STL--vector模拟实现_第3张图片

结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。

四、resize方法

STL--vector模拟实现_第4张图片

void resize(size_t n,const T& val=T()) {
     
	if(n>capacity()){
     
		reserve(n);		//第二种情况,要先进行扩容
	}
	
	if(n<size()){
     		//第一种情况,n
		_finish=n+_start;	
	}else{
     
		while(_finish!=_start+n){
     
			*_finish=val;
			++_finish;
		}
	}
}

五、insert、push_back 增方法

STL--vector模拟实现_第5张图片

void push_back(const T& val){
     
	check_capacity();
	*_finish=val;
	++_finish;
}

iterator insert(iterator pos,const T& val){
     
	assert(pos>=_start&&pos<=_finish);		pos==_finish时在vector的末尾插入
	size_t gap=pos-_start;//为了重新计算pos的位置,所以需要保存距离
	check_capacity();
	pos=_start+gap;	//如果发生了扩容需要重新计算pos迭代器的位置
	iterator end=_finish-1; //计算最后一个元素
	while(end>=pos){
     	//将pos迭代器以及以后的元素依次往后移动
		*(end+1)=*end;
		--end;
	}
	*pos=val;
	++_finish;
	return pos;
}

六、erase、pop_back删方法

iterator erase(iterator pos){
     
	assert(pos>=_start&&pos<_finish);	//pos不能等于_finish
	iterator it=pos+1;
	while(it!=_finish){
     
		*(it-1)=*it;
		--it;
	}
	--_finish;
	return pos;
}

void pop_back(){
     
	assert(_finish>_start);
	--_finish;
}

七、operator[] 改方法

T& operator[](size_t pos){
     
	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);
}

template<class InputIterator>
vector(InputIterator first,InputIterator last)	
	:_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
{
     
	reserve(last - first);
	while(first!=last){
     
		push_back(*first);
		++first;
	}
}

vector<T>& operator=(vector<T> v){
     	//现代写法
	swap(v);
	return *this;
}

vector(const vector<T> &val)
	:_start(nullptr),_finish(nullptr),end_of_storage(nullptr)
{
     
	vector<T> tmp(val.begin(),val.end());
	swap(tmp);
}

九、整合代码

#pragma once
#include

namespace Myvector {
     

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

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

		const_iterator begin() const{
     
			return _start;
		}

		const_iterator end() const{
     
			return _finish;
		}

		size_t size(){
     
			return _finish - _start;
		}

		size_t capacity() {
     
			return end_of_storage - _start;
		}
		vector():
		_start(nullptr),
		_finish(nullptr),
		end_of_storage(nullptr)
		{
     }

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

		template<class InputIterator>
		vector(InputIterator first, InputIterator last) :
			_start(nullptr), _finish(nullptr), end_of_storage(nullptr)
		{
     
			reserve(last - first);
			while (first != last) {
     
				push_back(*first);
				++first;
			}
		}

		vector(const vector<T>& val) :
			_start(nullptr), _finish(nullptr), end_of_storage(nullptr)
		{
     
			vector<T> tmp(val.begin(), val.end());
			swap(tmp);
		}

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

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

		void resize(size_t n,const T& val=T()) {
     
			if (n > capacity()) {
     
				reserve(n);
			}

			if (n<size()) {
     
				_finish = _start+n;
			}
			else {
     
				while (_finish != _start + n) {
     
					*_finish = val;
					++_finish;
				}
			}
		}

		void reserve(size_t n) {
     
			
			if (n > capacity()) {
     
				size_t sz = size();
				T* tmp = new T[n];
				//memcpy(tmp,_start,sizeof(T)*size()); //出现深浅拷贝问题
				for (size_t i = 0; i < sz; i++) {
     
					tmp[i] = _start[i];
				}
				delete[] _start;
				_start = tmp;
				_finish = _start + sz;
				end_of_storage = _start + n;
			}
		}

		void check_capacity() {
     
			if (_finish == end_of_storage) {
     
				size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);
			}
		}

		void push_back(const T&val) {
     
			check_capacity();
			*_finish = val;
			++_finish;
		}

		iterator insert(iterator pos,const T& val) {
     
			assert(pos>=_start&&_finish>=pos);
			size_t posi = pos - _start;
			check_capacity();
			pos = _start + posi;
			iterator end = _finish;
			while (end >= pos) {
     
				*(end + 1) = *end;
				--end;
			}
			*pos = val;
			++_finish;
			return pos;
		}

		void pop_back() {
     
			assert(_finish > _start);
			--_finish;
		}

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

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

	private:
		iterator _start;
		iterator _finish;
		iterator end_of_storage;
	};
}

你可能感兴趣的:(STL,C/C++,c++,stl)