C++|容器,容器的空间配置器

容器是一种容纳特定类型对象的集合
C++的容器可以分为两类 顺序容器关联容器

顺序容器中 元素的排放顺序是与其加入容器时的位置相对应的 这种顺序不依赖与元素的值
关联容器中,元素的位置由相关量的关键字值决定。也就是所关联容器中元素的位置与关键字有关

一个顺序容器 vector

#include <iostream>
using namespace std;

template <typename T,typename alloc=Allocator<T>>
class vector
{
public:
	vector(int size =10):
		_first(new T[size]),
		_last(_first),
		_end(_first+size)
	{}
	~vector()
	{
		delete[]_first;
		_first = _last = _end = nullptr;
	}
	vector(const vector<T> &rhs)
	{
		int size = rhs._end - rhs._first;
		_first = new T[size];
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			_first[i] = rhs._first[i];
		}
		_last = _first + len;
		_end = _first + size;
	}

	vector<T>& operator=(const vector<T> &rhs)
	{
		if (this == &rhs) return *this;
		delete[]_first;
		int size = rhs._end - rhs._first;
		_first = new T[size];
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			_first[i] = rhs._first[i];
		}
		_last = _first + len;
		_end = _first + size;
		return *this;
	}

	void push_back(const T &val)//向容器末尾添加元素
	{
		if (full())  expand();
		*_last++ = val;
}
	void pop_back()           //从容器末尾删除元素
	{
		if (empty()) return;
		--_last;
	}

	T back()const         //返回容器末尾元素的值
	{
		return *(_last - 1);
	}
	bool full()const
	{
		return _last == _end;
	}
	bool empty()const
	{
		return _last == _first;
	}


private:
	T *_first;    //指向数组起始的位置
	T *_last;     //指向数组中有效元素的后继位置
	T *_end;      //指向数组空间的后继位置
	alloc _allocator;//定义容器的空间配置器对象

	void expand()      //顺序容器的二倍扩容
	{
		int size = _end - _first;
		T *ptmp = new T[size * 2];

		for (int i = 0; i < size; ++i)
		{
			ptmp[i] = _first[i];
		}
		delete[]_first;
		_first = ptmp;
		_last = _first + size;
		_end = _first + 2 * size;
	}
};

int main()
{

	vector <int> vec;
	for (int i = 0; i < 20; i++)
	{
		vec.push_back(rand() % 100);
	}
	while (!vec.empty())
	{
		cout << vec.back() << " ";
		vec.pop_back();
	}
	cout << endl;
	return 0;
}

这样的容器存在问题,当我们使用一个类类型实例化一个容器时,因为new的使用,不仅做了开辟内存还构造了对象
需要把内存开辟对象构造分开处理
析构容器有效的元素,然后释放_first指向的堆内存
要把对象析构内存释放分离开
未解决此问题,引入容器的空间适配器 allocator
做四件事 内存开辟 内存释放 对象构造 对象析构
需要把内存开辟和对象构造分开处理
析构容器有效的元素,然后释放_first指向的堆内存
要把对象析构和内存释放分离开

容器的空间配置器

template<typename T>
class Allocator
{
	T* allocate(size_t size)
	{
		return (T*)molloc(sizeof(T)*size);
	}
	void deallocate(T *p)
	{
		free(p);
	}
	void construct(T* p, const T &val)
	{
		new(p) T(val);
	}

	void destory(T *p)
	{
		p->~T();
	}
};
template <typename T,typename alloc=Allocator<T>>
class vector
{
public:
	vector(int size =10):
		_last(_first),
		_end(_first+size)
	{
		_first = _allocator.allocate(size);
	}
	~vector()
	{
		//delete[]_first;
		for (T *p = _first; p != _last; ++p)
		{
			_allocator.destroy(p);
		}
		_allocator.deallocate(_first);
		_first = _last = _end = nullptr;
	}
	vector(const vector<T> &rhs)
	{
		int size = rhs._end - rhs._first;
		//_first = new T[size];
		_first = _allocator.allocate(size);
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			//_first[i] = rhs._first[i];
			_allocator.construct(_first + i, rhs._first[i]);
		}
		_last = _first + len;
		_end = _first + size;
	}

	vector<T>& operator=(const vector<T> &rhs)
	{
		if (this == &rhs) return *this;
		//delete[]_first;
		for (T *p = _first; p != _last; ++p)
		{
			_allocator.destroy(p);
		}
		_allocator.deallocate(_first);
		int size = rhs._end - rhs._first;
		//_first = new T[size];
		_first = _allocator.allocate(size);
		int len = rhs._last - rhs._first;
		for (int i = 0; i < len; ++i)
		{
			//_first[i] = rhs._first[i];
			_allocator.construct(_first + i, rhs._first[i]);
		}
		_last = _first + len;
		_end = _first + size;
		return *this;
	}

	void push_back(const T &val)//向容器末尾添加元素
	{
		if (full())  expand();
		//*_last++ = val;
		_allocator.construct(_last, val);
		_last++;
}
	void pop_back()           //从容器末尾删除元素
	{
		if (empty()) return;
		//--_last;
		--_last;
		_allocator.destroy(_last);

	}

	T back()const         //返回容器末尾元素的值
	{
		return *(_last - 1);
	}
	bool full()const
	{
		return _last == _end;
	}
	bool empty()const
	{
		return _last == _first;
	}


private:
	T *_first;    //指向数组起始的位置
	T *_last;     //指向数组中有效元素的后继位置
	T *_end;      //指向数组空间的后继位置
	alloc _allocator;//定义容器的空间配置器对象

	void expand()      //顺序容器的二倍扩容
	{
		int size = _end - _first;
		//T *ptmp = new T[size * 2];
		T *ptmp = _allocator.allocate(2 * size);

		for (int i = 0; i < size; ++i)
		{
			//ptmp[i] = _first[i];
			_allocator.construct(ptmp + i, _first[i]);
		}
		//delete[]_first;
		for (T *p; p != _last; ++p)
		{
			_allocator.destroy(p);
		}
		_allocator.deallocate(_first);
		_first = ptmp;
		_last = _first + size;
		_end = _first + 2 * size;
	}
};




int main()
{

	vector <int> vec;
	for (int i = 0; i < 20; i++)
	{
		vec.push_back(rand() % 100);
	}
	while (!vec.empty())
	{
		cout << vec.back() << " ";
		vec.pop_back();
	}
	cout << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值