C++ —— STL容器【vector】模拟实现

C++ —— STL容器【vector】模拟实现_第1张图片

本章代码gitee仓库:vector模拟实现、vector源码

文章目录

  • 0. 搭个框架
  • 1. 成员
  • 2. 构造函数 & 析构函数 & 拷贝构造
  • 3. 迭代器
  • 4. operator[] & operator=
  • 5. 容器的容量 & 个数
  • 6. 扩容
  • 7. 插入 & 删除操作

0. 搭个框架

#include
#include
#include
#include
using std::cout;
using std::endl;
namespace myvector
{
	template<typename T>
	class vector
    {
        public:
        	typedef T* iterator;
        	typedef const T* const_iterator;
        private:
    }
    
    //代码测试区
    void t1(){}
    //...
}

1. 成员

看源码发现vector是类模板定义的,成员是采用迭代器进行管理

C++ —— STL容器【vector】模拟实现_第2张图片

iterator _start;	//初始位置
iterator _finish;	//结束位置
iterator _end_of_storage;	//容量

2. 构造函数 & 析构函数 & 拷贝构造

当涉及到容器类时,通常有一些关键函数,如构造函数、析构函数和拷贝构造函数,它们负责初始化容器对象、销毁对象和进行对象的拷贝等

这里注意拷贝构造要实现的是深拷贝

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)
{
	resize(n, val);
}
//有选择
vector(int n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	resize(n, val);
}

//拷贝构造
vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	size_t vSize = v.size();
	if (vSize > 0)
	{
		_start = new T[vSize];
        //深拷贝
		for (size_t i = 0; i < vSize; i++)
		{
			_start[i] = v._start[i];
		}
		_finish = _start + vSize;
		_end_of_storage = _start + vSize;
	}
}
//迭代器初始化
template<typename InpuIterator>
vector(InpuIterator first, InpuIterator last)
	:_start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
//析构
~vector()
{
	if (_start)
	{
		delete[] _start;
		_start = _finish = _end_of_storage = nullptr;
	}
}

3. 迭代器

加上const,兼容具有常属性的元素

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

4. operator[] & 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];
}

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

5. 容器的容量 & 个数

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

6. 扩容

void reserve(size_t n)
{
	if (capacity() < n)
	{
		const size_t old_size = size();
		iterator tmp = new T[n];
		//	_start不为空挪数据
		if (_start)
		{
            //实现深拷贝
            //memcpy(tmp, _start, sizeof(T) * old_size);
			for (size_t i = 0; i < old_size; ++i)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}
		_start = tmp;
		_finish = tmp + old_size;
		_end_of_storage = _start + n;
	}
}

void resize(size_t new_size, const T& x = T())
{
	if (new_size < size())
		_finish = _start + new_size;
	else
	{
		reserve(new_size);
		while (_finish != _start + new_size)
		{
			*_finish = x;
			++_finish;
		}
	}
}

7. 插入 & 删除操作

指定位置插入/删除时,要注意迭代器失效的问题,采用iterator为返回类型,可以接收修改后的位置

迭代器失效:
在对容器进行插入和删除操作时,特别是涉及重新分配内存的情况下,会导致迭代器失效。
插入元素可能导致插入位置之后的元素迭代器失效,而删除元素可能导致删除位置之后的元素迭代器失效。
一旦迭代器失效,对其进行解引用或使用会导致未定义的行为

void push_back(const T& x)
{
	insert(end(), x);
	/*if (_finish == _end_of_storage)
	{
		reserve(capacity() == 0 ? 4 : 2 * capacity());
	}
	*_finish = x;
	_finish++;*/
}
void pop_back()
{
	--_finish;
}
iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);
	if (_finish == _end_of_storage)
	{
		size_t n = pos - begin();
		reserve(capacity() == 0 ? 4 : 2 * capacity());
		pos = begin() + n;
	}
	iterator end = _finish - 1;
	while (pos <= end)
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = x;
	++_finish;
	return pos;
}
iterator erase(iterator pos)
{
	assert(pos >= _start && pos < _finish);
	if (pos+1 != _finish)
	{
		iterator it = pos + 1;
		while (it != _finish)
		{
			*(it-1) = *it;
			++it;
		}
	}
	--_finish;
	return pos;
}

这里还是要注意深浅拷贝,自定义类型一定是要进行深拷贝的。

那么本期的分享就到这里,我们下期再见,如果还有下期的话。

你可能感兴趣的:(原创,C++,c++,开发语言,C语言)