[C++]vector及其模拟实现

容量和大小相关函数:

                                        size和capacity

                ​​​​​​​        ​​​​​​​        ​​​​​​​        reserve

                ​​​​​​​        ​​​​​​​        ​​​​​​​        resize

                ​​​​​​​        ​​​​​​​        ​​​​​​​        empty和clear

                ​​​​​​​        ​​​​​​​        修改容器内容相关函数:

                ​​​​​​​        ​​​​​​​        ​​​​​​​        push_back

                ​​​​​​​        ​​​​​​​        ​​​​​​​        pop_back

                ​​​​​​​        ​​​​​​​        ​​​​​​​        insert

                ​​​​​​​        ​​​​​​​        ​​​​​​​        erase

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​swap

                ​​​​​​​        ​​​​​​​        访问容器相关函数:

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​operator[ ]

                                vector模拟实现整体代码


C++:vector的模拟实现

vector中各函数接口介绍

namespace wjq
{
	template 
	class vector
	{
	public:
		//构造函数
		vector();
		vector(size_t n, const T& val = T());
		vector(int n, const T& val = T());
		template 
		vector(InputIterator first, InputIterator last);

		//拷贝构造
		void swap(vector& v);
		vector(const vector& v);

		//赋值运算符重载
		vector& operator=(vector v);

		//析构函数
		~vector();

		//迭代器
		typedef T* iterator;
		iterator begin();
		iterator end();
		const iterator begin()const;
		const iterator end()const;

		//访问容器相关函数
		T& operator[](size_t pos);
		const T& operator[](size_t pos)const;

		//reserve接口
		void reserve(size_t n);

		//resize接口
		void resize(size_t n, T val = T());

		//push_back/pop_back接口
		void push_back(const T& val);
		void pop_back();

		//insert和erase接口
		iterator insert(iterator pos, const T& val);
		iterator erase(iterator pos);

		//小接口
		size_t size()const;
		size_t capacity()const;
		bool empty()const;
		void clear();
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}

vector中成员变量概述

[C++]vector及其模拟实现_第1张图片

默认成员函数:

构造函数1 — 无参构造

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

[C++]vector及其模拟实现_第2张图片

构造函数2——n个val的构造

vector(size_t 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);
	}
}

[C++]vector及其模拟实现_第3张图片

[C++]vector及其模拟实现_第4张图片

[C++]vector及其模拟实现_第5张图片

构造函数3——n个val的重载

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

[C++]vector及其模拟实现_第6张图片

构造函数4——迭代器区间构造

template 
vector(InputIterator first, InputIterator last)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
        ++first;
	}
}

[C++]vector及其模拟实现_第7张图片

析构函数

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

[C++]vector及其模拟实现_第8张图片

拷贝构造函数

传统写法:

vector(const vector& v)
	:_start(nullptr)
	,_finish(nullptr)
	,_endofstorage(nullptr)
{
		_start = new T[v.capacity()];
		for (size_t i = 0; i < v.size(); ++i)
		{
			_start[i] = v[i];
		}
		_finish = _start + v.size();
		_end_of_storage = _start + v.capacity();
}

注意:将容器当中的数据一个个拷贝过来时不能使用memcpy函数,当vector存储的数据是内置类型或无需进行深拷贝的自定义类型时,使用memcpy函数是没什么问题的,但当vector存储的数据是需要进行深拷贝的自定义类型时,使用memcpy函数的弊端就体现出来了,例如,当vector存储的是string类的时候:

[C++]vector及其模拟实现_第9张图片

并且vector当中存储的每一个string都指向自己所存储的字符串

[C++]vector及其模拟实现_第10张图片

如果此时我们使用的是memcpy函数进行拷贝构造的话,那么拷贝构造出来的vector当中存储的每个string的成员变量的值将与被拷贝的vector当中存储的每个string的成员变量的值相同,即两个vector当中的每个对应的string成员都指向同一个字符串空间.

[C++]vector及其模拟实现_第11张图片

这显然不是我们想得到的结果,那么所给代码是如何解决这个问题的呢?

[C++]vector及其模拟实现_第12张图片

代码中看似是使用普通的"="将容器当中的数据一个一个拷贝过来,实际上是调用了赋值运算符重载函数,而string类的赋值运算符重载是深拷贝,所以拷贝结果是这样的:

[C++]vector及其模拟实现_第13张图片

[C++]vector及其模拟实现_第14张图片

现代写法一:

vector(const vector& v)
	: _start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(v.capacity());
	for (const auto& e : v)
	{
		push_back(e);
	}
}

[C++]vector及其模拟实现_第15张图片

现代写法二:

void swap(vector& v)//一定要加引用,不然拷贝构造函数调用swap会引发无限拷贝
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_end_of_storage, v._end_of_storage);
}
vector(const vector& v)
	: _start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	vector tmp(v.begin(), v.end());
	swap(tmp);
}

[C++]vector及其模拟实现_第16张图片

赋值运算符重载

传统写法:

vector& operator=(const vector& v)
{
	if (this != &v)
	{
		delete[] _start;
		_start = new T[v.capacity()];
		for (size_t i = 0; i < v.size(); ++i)
		{
			_start[i] = v[i];
		}
		_finish = _start + v.size();
		_end_of_storage = _start + v.capacity();
		return *this;
	}
}

[C++]vector及其模拟实现_第17张图片

现代写法:

赋值运算符重载的参数传参并没有使用引用传参,因为这样可以直接调用vector的拷贝构造函数,然后将这个拷贝构造出来的容器v与其进行交换,此时就完成了赋值操作,而容器v在函数调用结束后时自动析构.

注意:赋值运算符重载的现代写法也是进行的深拷贝,只不过是调用的vector的拷贝构造函数进行的深拷贝,在赋值运算符重载函数当中仅仅是将深拷贝出来的对象与其进行了交换而已.

vector& operator=(vector v)//能解决自己给自己赋值的问题
{
	swap(v);
	return *this;
}

[C++]vector及其模拟实现_第18张图片

迭代器相关函数:

begin和end

typedef T* iterator;
iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}
const iterator begin()const
{
	return _start;
}
const iterator end()const
{
	return _finish;
}

[C++]vector及其模拟实现_第19张图片

容量和大小相关函数:

size和capacity

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

[C++]vector及其模拟实现_第20张图片

reserve

void reserve(size_t n)
{
	//扩容
	if (n > capacity())
	{
		size_t oldSize = size();
		T* tmp = new T[n];
		if (_start != nullptr)
		{
			for (size_t i = 0; i < oldSize; ++i)
			{
				tmp[i] = _start[i];//调用赋值运算符重载完成深拷贝
			}
			delete[] _start;
		}
		_start = tmp;
		_finish = _start + oldSize;
		_end_of_storage = _start + n;
	}
}

[C++]vector及其模拟实现_第21张图片

[C++]vector及其模拟实现_第22张图片

[C++]vector及其模拟实现_第23张图片

[C++]vector及其模拟实现_第24张图片

[C++]vector及其模拟实现_第25张图片

[C++]vector及其模拟实现_第26张图片

[C++]vector及其模拟实现_第27张图片

[C++]vector及其模拟实现_第28张图片​​​​​​​

resize

void resize(size_t n, T val = T())
{
	if (n > capacity())
	{
		reserve(n);
		while (_finish < _start + n)
		{
			*_finish = val;
			++_finish;
		}
	}
	else if (n > size())
	{
		while (_finish < _start + n)
		{
			*_finish = val;
			++_finish;
		}
	}
	else
	{
		_finish = _start + n;
	}
}

[C++]vector及其模拟实现_第29张图片

empty和clear

bool empty()const
{
	return _start == _finish;
}
void clear()
{
	_finish = _start;
}

[C++]vector及其模拟实现_第30张图片

修改容器内容相关函数:

push_back

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

[C++]vector及其模拟实现_第31张图片

pop_back

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

[C++]vector及其模拟实现_第32张图片

insert

iterator insert(iterator pos, const T& val)
{
	assert(pos >= _start && pos < _finish);
	//判断扩容
	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start;
		size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
		reserve(newCapacity);
		pos = _start + len;
	}
	//挪动数据
	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		--end;
	}
	//填入数据
	*pos = val;
	++_finish;
	return pos;
}

[C++]vector及其模拟实现_第33张图片

erase

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

[C++]vector及其模拟实现_第34张图片

swap

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

[C++]vector及其模拟实现_第35张图片

访问容器相关函数:

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

[C++]vector及其模拟实现_第36张图片

vector模拟实现整体代码:

#pragma once
#include 
#include 
using std::cout;
using std::cin;
using std::endl;
namespace jly
{
	template 
	class vector
	{
	public:
		//构造函数
		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{}
		vector(size_t 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);
			}
		}
		vector(int n, const T& val = T())//多重载一个int版本的构造,解决调函数不明确的问题
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}
 
		template 
		vector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			while (first != last)
			{
				push_back(*first++);
			}
		}
		//拷贝构造
		void swap(vector& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}
		vector(const vector& v)
			: _start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			vector tmp(v.begin(), v.end());
			swap(tmp);
		}
		//vector(const vector& v)//写法二
		//	: _start(nullptr)
		//	, _finish(nullptr)
		//	, _end_of_storage(nullptr)
		//{
		//	reserve(v.capacity());
		//	for (const auto& e : v)
		//	{
		//		push_back(e);
		//	}
		//}
		//赋值运算符重载
		vector& operator=(vector v)
		{
			swap(v);
			return *this;
		}
		//析构函数
		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}
		//迭代器
		typedef T* iterator;
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}
		const iterator begin()const
		{
			return _start;
		}
		const iterator end()const
		{
			return _finish;
		}
		T& operator[](size_t pos)
		{
			return _start[pos];
		}
		const T& operator[](size_t pos)const
		{
			return _start[pos];
		}
		//reserve接口
		void reserve(size_t n)
		{
			//扩容
			if (n > capacity())
			{
				size_t oldSize = size();
				T* tmp = new T[n];
				if (_start != nullptr)
				{
					//memcpy(tmp, _start, sizeof(T) * oldSize);
					for (size_t i = 0; i < oldSize; ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + oldSize;
				_end_of_storage = _start + n;
			}
		}
		//resize接口
		void resize(size_t n, T val = T())
		{
			if (n > capacity())
			{
				reserve(n);
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else if (n > size())
			{
				while (_finish < _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
			else
			{
				_finish = _start + n;
			}
		}
		//push_back/pop_back接口
		void push_back(const T& val)
		{
			if (_finish == _end_of_storage)
			{
				size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newCapacity);
			}
			*_finish = val;
			++_finish;
		}
		void pop_back()
		{
			assert(!empty());
			--_finish;
		}
		//insert和erase接口
		iterator insert(iterator pos, const T& val)
		{
			assert(pos >= _start && pos < _finish);
			//判断扩容
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;
				size_t newCapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newCapacity);
				pos = _start + len;
			}
			//挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			//填入数据
			*pos = val;
			++_finish;
			return pos;
		}
		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator begin = pos + 1;
			while (begin < _finish)
			{
				*(begin - 1) = *begin;
				++begin;
			}
			--_finish;
			return pos;
		}
        
		//小接口
		size_t size()const
		{
			return _finish - _start;
		}
		size_t capacity()const
		{
			return _end_of_storage - _start;
		}
		bool empty()const
		{
			return _start == _finish;
		}
		void clear()
		{
			_finish = _start;
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};
}

你可能感兴趣的:(c++,算法,开发语言,1024程序员节)