STL之vector类的模拟实现

博客主页:C-SDN花园GGbond

⏩ 文章专栏:玩转c++

目录

1. vector的成员变量 

2. vector的成员函数 

2.1. vector的迭代器 

2.2. vector的初始化与销毁 

2.2.1. 构造函数与拷贝构造

2.2.2. 赋值重载与析构函数 

2.3. vector的容量操作 

2.3.1. 有效长度与容量大小

2.3.2. 容量操作 

2.4. vector的访问操作 

2.5. vector的修改操作 

2.5.1. 常见的修改操作 

3. 源码 

3.1 vector.h 

3.2  test.cpp 

3.3 运行结果 


为了让我们更加深入理解vector,接下来我们将模拟实现一个·简易版的vector。而为了和STL库中的vecotr以示区分,我们将使用命名空间HTD对其封装。

1. vector的成员变量 

vector的底层其实就是我们之前在数据结构学习的顺序表,但是与顺序表不同的是vector的成员变量是三个迭代器,也可以说是三个指针。 

STL之vector类的模拟实现_第1张图片

其中_start指向起始位置,_finish指向有效数据末尾的后一个位置,最后_end_of_storage指向容量大小末尾的后一个位置。

namespace betty 
{
	template
	class vector 
    {
	public:
    //...
	private:
		iterator _start;//指向有效数据的头
		iterator _finish;//指向有效数据的尾
		iterator _end_of_storage;//指向容量的尾

	};
}

2. vector的成员函数 

2.1. vector的迭代器 

首先我们来模拟实现一下迭代器iterator,而在vector中迭代器iteratorstring中的迭代器类似就是一个指针。所以我们直接使用typedef实现 

typedef char* iterator;//普通迭代器
typedef const char* const_iterator;//const迭代器

接下来我们来实现begin()end(),其中begin()指向的是数组的起始位置即_start,而end指向有效长度最后的下一位即_finish的位置。 实现完普通迭代器之后,我们可以顺便重载一个const_iterator的版本。

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

我们知道在vector中还有一个反向迭代器,这个我们在之后会统一实现。 

2.2. vector的初始化与销毁 
2.2.1. 构造函数与拷贝构造

我们之前在学习vector时知道其初始化方式有很多,可以通过默认构造函数给其初始化,n个val初始化,也可以通过迭代器初始化。

首先我们写一个默认构造函数,将其所有变量都设为空。

vector()//无参默认构造
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{}
vector(size_t n,const T& val=T())//n个val初始化
	:_start(nullptr)
	,_finish(nullptr)
	,_end_of_storage(nullptr)
{
	reserve(n);
	while(n--)
	{
		push_back(val);
	}
}
vector(int n, const T& val = T())//n个val初始化
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(n);
	while(n--)
	{
		push_back(val);
	}
}
template
vector(inputiterator fist, inputiterator last)//迭代器区间初始化
{
	while (fist != last)
	{
		push_back(*fist);
		fist++;
	}
}
//拷贝构造
//vector(const vector& v)
//{
//	_start = new T[v.capacity()];
//	for (size_t i = 0; i < v.size(); i++)
//	{
//		_start[i] = v._start[i];
//	}
//	_finish = _start + v.size();
//	_end_of_storage = _start + v.capacity();
//}
vector(const vector& v)
{
	reserve(v.capacity());
	for (size_t i = 0; i < v.size(); i++)
	{
		push_back(v._start[i]);
	}
}

至于为什么要同时重载intsize_t两种不同类型,那是为了防止在传两个int类型的参数时被编译器交给模版InputIterator识别,然后报错。 拷贝构造也十分简单,直接拷贝就行,但不能利用memcpy()等库函数进行拷贝,因为这些函数都是进行的浅拷贝。如果模版参数Tstringvector等自定义类型,当程序结束回收内存时就会发生内存错误。

2.2.2. 赋值重载与析构函数 
vector operator = (vector v)
{
    swap(v);
    return *this;
}

实现析构函数,只需要清理资源即可 

~vector()
{
    delete[]_start;
    _start = _finish = _end_of_storage = nullptr;
}
2.3. vector的容量操作 

2.3.1. 有效长度与容量大小

首先我们先实现返回数组有效长度的size() 与容量大小的capacity()。并且为了适配const对象,最后用const修饰this指针。

size_t size() const
{
    return _finish - _start;
}
size_t capacity() const
{
    return _end_of_storage - _start;
}
2.3.2. 容量操作 

 接下来我们来实现扩容函数reserve()与·resize(),其中reserve()最简单,只要新容量大于旧容量就发生扩容,其中注意需要提前记录size大小,防止数组异地扩容原数组释放之后找不到原数组大小。

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t old_size = size();
		T* tmp = new T[n];
		//memcpy(tmp, _start, sizeof(T) * size());memcpy浅拷贝
		for (size_t i = 0; i < size(); i++)
		{
			tmp[i] = _start[i];
		}
		delete[]_start;
		_start = tmp;
		_finish = _start + old_size;
		_end_of_storage = _start + n;
	}
}

resize()的逻辑就比较复杂,需要分三种情况讨论。设字符串原来有效长度为size,容量为capacity,新容量为n 

  1. n时,resize会删除有效字符到指定大小。
  2. size时,resize会补充有效字符(默认为0)到指定大小。
  3. n>capacity时,resize会补充有效字符(默认为0)到指定大小。

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. vector的访问操作 

 为了符合我们C语言访问数组的习惯,我们可以先重载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];
}

们也可以实现front()back()函数。 

// 可读可写
char& front()
{
	return _start[0];
}
char& back()
{
	return _start[_size() - 1];
}
// 可读不可写
const char& front()const
{
	return _start[0];
}
const char& back()const
{
	return _start[_size() - 1];
}
2.5. vector的修改操作 
2.5.1. 常见的修改操作 

首先我们将实现两个常用的修改函数:push_back()pop_back()。 

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

随后我们来实现数组的交换swap()函数,我们知道vector的交换其实就是指针_start_finish_end_of_storage的交换 

void swap(vector& v)
{
    std::swap(_start, v._start);
    std::swap(_finish, v._finish);
    std::swap(_end_of_storage, v._end_of_storage);
}

3. 源码 

3.1 vector.h 

#pragma once
#include
#include
using namespace std;
namespace HTD
{
	template
	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() const
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}
		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			_finish++;
		}
		void pop_back()
		{
			--_finish;
		}
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t old_size = size();
				T* tmp = new T[n];
				//memcpy(tmp, _start, sizeof(T) * size());memcpy浅拷贝
				for (size_t i = 0; i < size(); i++)
				{
					tmp[i] = _start[i];
				}
				delete[]_start;
				_start = tmp;
				_finish = _start + old_size;
				_end_of_storage = _start + n;
			}
		}
		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++;
				}
			}
		}
		vector()//无参默认构造
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{}
		vector(size_t n,const T& val=T())//n个val初始化
			:_start(nullptr)
			,_finish(nullptr)
			,_end_of_storage(nullptr)
		{
			reserve(n);
			while(n--)
			{
				push_back(val);
			}
		}
		vector(int n, const T& val = T())//n个val初始化
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			while(n--)
			{
				push_back(val);
			}
		}
		template
		vector(inputiterator fist, inputiterator last)//迭代器区间初始化
		{
			while (fist != last)
			{
				push_back(*fist);
				fist++;
			}
		}
		//拷贝构造
		//vector(const vector& v)
		//{
		//	_start = new T[v.capacity()];
		//	for (size_t i = 0; i < v.size(); i++)
		//	{
		//		_start[i] = v._start[i];
		//	}
		//	_finish = _start + v.size();
		//	_end_of_storage = _start + v.capacity();
		//}
		vector(const vector& v)
		{
			reserve(v.capacity());
			for (size_t i = 0; i < v.size(); i++)
			{
				push_back(v._start[i]);
			}
		}
		void swap(vector& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);

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

		~vector()
		{
			delete[]_start;
			_start = _finish = _end_of_storage=nullptr;
		}
		T& operator[](size_t pos)//可读可写
		{
			assert(pos < size());
			return _start[pos];
		}
		const T& operator[](size_t pos)const//可读不可写
		{
			assert(pos < size());
			return _start[pos];
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};


	template
	void print_vector(const vector& v)
	{
		// 规定,没有实例化的类模板里面取东西,编译器不能区分这里const_iterator
		// 是类型还是静态成员变量
		typename vector::const_iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it<<" ";
			++it;
		}
		cout << endl;
		for (auto e : v)
		{
			cout << e<<" ";
		}
		cout << endl;
	}


	void vector_test01()
	{
		vector v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);
		/*print_vector(v1);
		vector v2(v1);
		
		print_vector(v2);*/
		vector v3;
		v3.push_back(33);
		v3.push_back(44);
		print_vector(v3);

		v3 = v1;
		print_vector(v3);

		v1.resize(8);
		print_vector(v1);
		cout << v1[2]<
3.2  test.cpp 
#include"vector.h"
int main()
{
	//HTD::vector_test01();
	HTD::vector_test01();
	return 0;
}
3.3 运行结果 

STL之vector类的模拟实现_第2张图片

你可能感兴趣的:(玩转c++,c++,开发语言)