11. 函数模板类模板实现vector顺序容器空间适配器

Posted 为了财务自由!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了11. 函数模板类模板实现vector顺序容器空间适配器相关的知识,希望对你有一定的参考价值。

// 模板的声明
template<typename T> 
bool compare(T a, T b)

	return a>b;


int main()

	compare<int>(20,30);
	//模板的实参推演!
	compare(20,30);

编译器优先把函数名看成普通函数,找不到的话,才考虑是个函数模板!:
compare (“aaa”,“bbb”);

模板不能分开文件定义(一个文件定义,一个文件使用)!因为编译产生符号,链接时找不到符号,出现错误!所以模板代码一般放在头文件.h中定义!那我如果就是要分开在另一个cpp文件定义怎么办呢?
在另一个cpp文件处写好可能的实例化类型:类似于
template bool compare(int,int);
template bool compare(double,double);

类模板

//实现栈容器
template<typename T>
class SeqStack //模板名称+类型参数列表=类名称

public:
	//构造和析构函数名不用加<T>,其他出现模板的地方需要加上类型参数列表
	SeqQueue(int size=10)
		:_pstack(new T[size])
		,_top(0)
		,_size(size)
	
	~SeqQueue()
	
		delete[] _pstack;
		_pstack=nullptr;
	
	SeqQueue(const SeqQueue<T>& stack)
		:_top(stack._top)
		,_size(stack._size)
	
		_pstack = new T[_size];
		//不要用memcpy进行拷贝(是个对象就不能用)
		for(int i=0;i<_top;++i)
		
			_pstack[i] = stack._pstack[i];
		
	
	SeqStack<T>& operqtor=(const SeqStack<T>& stack)
	
		if(this == &syack)
			return *this;
		delete[] _pstack;
		_top=stack._top;
		_size=stack._size;
		_pstack=new T[_size];
		for(int i=0;i<_top;++i)
		
			_pstack[i] = stack._pstack[i];
		
	

	void push(const T& val)
	
		if(full())
		
			expand();
		
		_pstack[top++]=val;
	
	void pop()
	
		if(empty())
			return;
		--_top;
	
	T top() const
	
		if(empty())
		
			throw "stack is empty!";
		
		return _pstack[top-1];
	
	bool full() const
	
		return _top == _size;
	
	bool empty() const
	
		return _top == 0;
	
private:
	T* _pstack;
	int _size;
	int _top;
	//顺序栈底层数组2倍方式扩容
	void expand()
	
		T* ptmp = new T[_size*2];
		for(int i=0;i<_top;++i)
		
			ptmp[i] = _pstack[i];
		
		delete[] _pstack;
		_pstack = ptmp;
		_size *= 2;
	
;
//vector
template<typename T>

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 ;
		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(T& val)
	
		if(full())
			expand();
		*_last=val;
		_last++;
	
	void pop_back()
	
		if(empty())
			return ;
		--_last;
	
	//返回容器末尾的值
	T back()const
	
		return *(_last-1);
	
	bool full()const
	
		return _last == _end;
	
	bool empty()const
	
		return _first == _last;
	
	int size()const
	
		return _last - _first;
	
private:
	T* _first;//指向数组起始位置
	T* _last;//指向数组中有效元素的后继位置
	T* _end;//指向数组空间的后继位置
	void expand()//2倍扩容
	
		int size = _end - _first;
		T* ptmp = new T[2*size];
		for(int i=0;i<size;i++)
		
			ptmp[i] = _first[i];
		
		delete[] _first;
		_first = ptmp;
		_last = _fist + size;
		_end = _first + size*2;
	

以上代码缺少空间适配器!

class Test

public:
	Test()cout << "Test()" << endl;
	~Test()cout << "~Test()" << endl;
;
//这回出现很多次构造与析构!因为自实现的vector内部实现是new出来的空间
//但是我们此时认为这个容器是空的,但是实际上已经默认有size个对象了!不合理!
vector<Test> vec;
//那么在pop_back时,内部实现是实现指针的移动就搞定了,这会造成对象内存没有释放!
//我们需要改进,pop_back时需要释放内存!

引入空间适配器!
allocator做四件事情:内存开辟/内存释放、对象构造/对象析构

template<typename T>
struct Allocator

	//负责内存开辟
	T* allocate(size_t size)
	
		return (T*)malloc(sizeof(T)*size);
	
	//负责内存释放!
	void deallocate(void* p)
	
		free(p);
	
	//负责对象构造!
	void construct(T* p,const T&val)
	
		new(p) T(val);//定位new,在指定的地址(p)存放val
	
	void destroy(T* p)
	
		p->~T();//~T()代表T类型析构函数
	
;

把上面的vector代码改进:

//vector
template<typename T,typename Alloc = Allocator<T>>

public:
	vector(int size=10,const Alloc& alloc = Allocator<T>())
		:_allocator(alloc)
	
		//_first=new T[size];
		_first = _allocator.allocate(size);
		_last=_first;
		_end=_first+size;
	
	//析构容器有效个数的元素,然后释放_first指针指向的堆内存
	~vector()
	
		//delete[] _first;
		for(T* p=_first;p!=_last;++p)
		
			//把_first指针指向的数组有效元素进行析构操作
			_allocator.destory(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 ;
		//delete[] _first;
		for(T* p=_first;p!=_last;++p)
		
			//把_first指针指向的数组有效元素进行析构操作
			_allocator.destory(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(T& val)
	
		if(full())
			expand();
		//*_last=val;
		//_last++;
		_allocator.construct(_last,val);
		_last++;
	
	void pop_back()
	
		if(empty())
			return ;
		--_last;
		_allocator.destroy(_last);
	
	//返回容器末尾的值
	T back()const
	
		return *(_last-1);
	
	bool full()const
	
		return _last == _end;
	
	bool empty()const
	
		return _first == _last;
	
	int size()const
	
		return _last - _first;
	
private:
	T* _first;//指向数组起始位置
	T* _last;//指向数组中有效元素的后继位置
	T* _end;//指向数组空间的后继位置
	Alloc _allocator;//定义容器的空间适配器对象!
	void expand()//2倍扩容
	
		int size = _end - _first;
		//T* ptmp = new T[2*size];
		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=_first;p!=_last;++p)
		
			_allocator.destroy(p);
		
		_allocator.deallocate(_first)
		_first = ptmp;
		_last = _fist + size;
		_end = _first + size*2;
	

以上是关于11. 函数模板类模板实现vector顺序容器空间适配器的主要内容,如果未能解决你的问题,请参考以下文章

用类模板实现容器(STL里面的vector)

Vector模板类的建立与实现

用类模板实现容器存储自定义数据类型(类似于STL里面的vector)

C++STL之ACM相关知识大全

C++ vector类型要点总结(以及各种algorithm算法函数)

C++中vector的用法