今天用模板实现了一个顺序栈。
/*
顺序栈
*/
#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!
请按任意键继续. . .