自定义可以存放任意类型(含智能指针)的顺序栈

本文介绍了一个使用模板实现的顺序栈,并探讨了如何有效管理栈内智能指针资源,确保智能指针在出栈时能够自动释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天用模板实现了一个顺序栈。

/*
顺序栈
*/
#ifndef _SEQ_STACK_H_
#define _SEQ_STACK_H_
#include <iostream>
using namespace std;

template<class T>
class SeqStack
{
public:
	SeqStack(unsigned int maxSize = 10);//栈最大值
	~SeqStack();//析构函数
	bool isEmpty() const;//是否为空
	bool isFull() const;//是否满了
	int size() const;//目前占大小
	T top()const;//返回栈顶元素,不删除
	bool push(const T& t);//入栈
	void pop();//出栈,不返回元素
	friend ostream& operator<<<>(ostream& out, const SeqStack<T>& s);//输出栈的友员函数
private:
	int nowTop;//目前栈顶
	int maxTop;//栈的最大值
	T* stack;//存储元素的动态数组
};

template<class T>
SeqStack<T>::SeqStack(unsigned int maxSize)
{
	stack = new T[maxSize];//如果new失败,抛出异常,malloc则是返回NULL
	maxTop = maxSize - 1;
	nowTop = -1;
}

template<class T>
SeqStack<T>::~SeqStack()
{
	delete[] stack;//删除指针
}

template<class T>
bool SeqStack<T>::isEmpty() const
{
	if (nowTop == -1)return true;
	else return false;
}

template<class T>
bool SeqStack<T>::isFull() const
{
	if (nowTop == maxTop)
		return true;
	else 
		return false;
}

template<class T>
int SeqStack<T>::size()const
{
	return nowTop + 1;
}

template<class T>
T SeqStack<T>::top()const
{
	if (!isEmpty())
		return stack[nowTop];
}

template<class T>
bool SeqStack<T>::push(const T& t)//用引用,避免了一次不必要的拷贝操作
{
	if (isFull())
		return false;
	stack[++nowTop] = t;//还是要复制一次
	return true;
}

template<class T>
void SeqStack<T>::pop()
{
	if (!isEmpty())
	{
		T t;
		stack[nowTop] = t;//重置原来的元素,这样也许可以将智能指针引用减一。
		nowTop--;
	}
}

template<class T>
ostream& operator<<(ostream& out, const SeqStack<T>& s)//
{
	for (int i = s.nowTop; i > -1; i--)
		out << s.stack[i] << endl;
	return out;
}

#endif

为了兼容智能指针,我希望在出栈时,智能指针能够自动释放。我的做法是出栈时,构建一个空的智能指针,存放在原来的位置,那么原来的智能指针就会自动销毁。这段代码是我自己想的办法,不知道还有没有更好的办法。毕竟新建一个对象会有一定开销。

template<class T>
void SeqStack<T>::pop()
{
	if (!isEmpty())
	{
		T t;
		stack[nowTop] = t;//重置原来的元素,这样也许可以将智能指针引用减一。
		nowTop--;
	}
}
我也考虑过将原来的置NULL,但是这样的话,如果栈的元素类型不是指针或者智能指针,而是其他类型就会报错。

stack[nowTop] = NULL;
下面是测试代码:

#include <iostream>
#include "SeqStack.h"
#include <memory>

using namespace std;

class A
{
public:
	A(){ cout << "A construct!" << endl; }
	~A(){ cout << "A destruct!" << endl; }

};
void test()
{	
	SeqStack<shared_ptr<A>> mStack;
	mStack.push(make_shared<A>());
	mStack.push(make_shared<A>());
	mStack.pop();
	mStack.pop();
	mStack.push(make_shared<A>());
	cout << "test" << endl;
}
void main()
{	
	test();
	system("pause");
}
当把这两句注释后的输出:

template<class T>
void SeqStack<T>::pop()
{
	if (!isEmpty())
	{
		//T t;
		//stack[nowTop] = t;//重置原来的元素,这样也许可以将智能指针引用减一。
		nowTop--;
	}
}
输出:可以看出当第三个智能指针入栈后,原来位置的智能指针才被释放了。函数执行完后,有两个析构,一个是栈中正常的元素,一个是之前没有被正常释放的元素。也就说,如果没有别的写入操作,智能指针的对象会一直存在栈中。

A construct!
A construct!
A construct!
A destruct!
test
A destruct!
A destruct!
请按任意键继续. . .


没有注释时,正常输出:执行pop函数后,智能指针马上被析构。

A construct!
A construct!
A destruct!
A destruct!
A construct!
test
A destruct!
请按任意键继续. . .





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值