模板栈(二)


基于模板栈(一)中简单模板栈的编写,接下来将对模板栈进行优化升级

简单模板栈描述如下:

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	SeqStack(int sz = 100):data(NULL),capacity(sz),pos(-1)//构造函数,初始化private成员
	{  data = new Type[capacity];//通过new运算符申请空间,并调用构造函数;  }
	void push(const Type &x)//入栈--改变对象状态,不能为常方法
	{  data[++pos] = x;  }
	void pop()//出栈--改变对象状态,不能为常方法
	{  --pos;  }
	Type & top()//得到栈顶元素
	{  return data[pos];  }
	const Type & top() const//得到栈顶元素
	{  return data[pos];  }
	bool empty() const//判空--不改变对象状态,常方法
	{  return size() == 0;  }
	size_t size() const//得到栈中元素--对象个数,不改变对象状态,常方法
	{  return pos+1;  }
	~SeqStack()//析构函数
	{  delete []data;//释放空间
	   data = NULL;capacity = 0;pos = -1;  }
};

简单模板栈存在的问题:
当该模板栈对象调用构造函数时,对象的指针data属性将会通过new申请空间并调用构造函数,创建capacity个对象,从而进行数据的入栈,而若主函数无数据的入栈,则会浪费内存空间,造成内存碎片化;同时模板栈对象类型不仅仅只是内置类型,还可以是自己定义的类型,因此为解决这种情况,我们将使用malloc以及定位new对模板栈进行优化。

1. 对构造函数SeqStack()进行优化:

不再使用运算符new申请空间并创建对象,而是通过malloc申请空间,不创建对象:

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	SeqStack(int sz = 100):data(NULL),capacity(sz),pos(-1)//构造函数,初始化private成员
	{  
		//data = new Type[capacity];//通过new运算符申请空间,并调用构造函数;  
		//通过malloc申请空间,但并不创建对象
		data = (Type*)malloc(sizeof(Type)*capacity);
	}

2. 对入栈函数void push()进行优化:

由于构造函数SeqStack()通过malloc申请空间,因此数据在进行入栈时,将通过定位new,在参数的地址空间完成对象的构建过程。

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	void push(const Type &x)//入栈--改变对象状态,不能为常方法
	{  
		//data[++pos] = x;
		//通过定位new完成对象的构建过程,在data[pos]的地址构建对象  
		new(&data[++pos]) Type(x);
	}
};

注意:
(1)类型名()------->表示构造函数;
(2)在优化构造函数之后,data[++pos] = x;将不再适用,理由:因为在构造函数中,通过malloc申请空间,得到的只是空间,不能在空间中进行赋值,而是要在空间中构建对象再进行赋值,所以只能对象赋值给对象,而不能对象赋值给空间;
(3)new(&data[++pos]) Type(x)含义:将通过图片详细描述
在这里插入图片描述
(4)对于求对象空间大小,需要注意对象的大小只是自身空间大小,并不包括堆区数据的大小(指针类型大小为4),如下:

template<class Type>
class Object
{
private:
	int value;
public:
	Object(int sz = 100):value(sz)//构造函数
	{  
		cout<<"creat Object"<<this<<endl;
	}
	~Object()//析构函数
	{  
		cout<<"destroy Object"<<this<<endl;
	}
};
int main()
{
	SeqStack<Object> objst;
	sizeof(objst);      //12
	Object obj(10);
	Objst.push(obj);
	sizeof(objst);	    //12
}

第一个sizeof:栈中还未创建对象,只是具有三个私有数据成员:Type *data、int capacity、int pos,指针所占空间4个字节,整型所占空间4个字节,因而12个字节;
第二个sizeof:栈中已创建空间,但.data是指针,指向所创建的对象,而对象在堆区存放,因而栈所占的空间大小仍是12;
具体空间可见上方图片

3. 对出栈函数void pop()进行优化:

简单模板栈的出栈函数只是将pos移动,则代表数据出栈,但并不是最合适的数据操作处理方式,因此为优化出栈函数,对象出栈时,将通过调用析构函数,将资源释放,但该空间并没有被销毁,还仍能继续使用。

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	void pop()//出栈--改变对象状态,不能为常方法
	{ 
		//--pos; 
		//将data[pos]对象调用析构函数,释放资源,但并没有销毁空间
		(&data[pos])->~Type(); 
		--pos;
	}
};

注意:
只是调用析构函数进行资源的释放,但并没有销毁空间

4. 对析构函数~SeqStack()进行优化:

基于前面对函数的优化,析构函数也将会随之优化,通过for循环,栈中每一个对象调用析构函数进行资源的释放,最后进行空间的销毁。

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	~SeqStack()//析构函数
	{  
		/*
		delete []data;//释放空间
		data = NULL;
		capacity = 0;
		pos = -1; 
		*/
		for(int i = 0;i<=top;i++)//调用析构函数,将资源释放
		{
			(&data[i])->~Type();
		}
		free(data);//销毁空间
		data = NULL;
		capacity = 0;
		pos = -1; 
	}
};

此模块为模板栈的一级优化,仍存在一些需要解决的问题,例如:栈满时应该如何操作?重载赋值函数和拷贝构造函数如何编写呢?

后续将会继续优化模板栈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值