#include <new>
template<class T1, class T2>
void construct(T1* p,const T2& val)
{
new (p) T1(val);//placement new
}
template <class T>
void destroy(T* p)
{
p->~T();
}
template <class FwdIter>
void destroy(FwdIter first,FwdIter last)
{
while (first != last)
{
destroy(&*first);
++first;
}
}
template <class T>
void swap(T& a,T& b)
{
T temp(a); a=b;b=temp;
}
template<class T>
class StackImpl
{
public:
StackImpl(size_t size):
v_(static_cast<T*>
(size == 0 ? 0 :operator new (sizeof(T)*size))),
vused_(0),
vsize_(size)
{}// new operator
~StackImpl()
{
destroy(v_,v_ + vused_);
operator delete (v_);
}
void Swap(StackImpl& other) throw()
{
swap(v_,other.v_);
swap(vsize_,other.vsize_);
swap(vused_,other.vused_);
}
T* v_;
size_t vsize_;
size_t vused_;
private:
StackImpl(const StackImpl& other);
StackImpl& operator=(const StackImpl& other);
};
template<class T>
class Stack
{
public:
Stack(size_t size=0):impl_(size)
{}
Stack(const Stack& other):impl_(other.impl_.vused_)
{
while(impl_.vused_ < other.impl_.vused_)
{
construct(impl_.v_+impl_.vused_,other.impl_.v_[impl_.vused_]);
++impl_.vused_;
}
}
Stack& operator=(const Stack& other)
{
Stack temp(other);
impl_.Swap(temp.impl_);
return *this;
}
~Stack()
{
}
bool Empty()
{
return 0 == impl_.vused_;
}
size_t Count()const
{
return impl_.vused_;
}
void Push(const T& t)
{
if(impl_.vused_ == impl_.vsize_)
{
Stack temp(2*impl_.vsize_ + 1);
while(temp.Count() < impl_.vused_)
{
temp.Push(impl_.v_[temp.Count()]);
}
temp.Push(t);
impl_.Swap(temp.impl_);
}
else
{
construct(impl_.v_+impl_.vused_,t);
++impl_.vused_;
}
}
void Pop()
{
if (impl_.vused_ == 0)
{
throw "pop from empty stack";
}
else
{
--impl_.vused_;
destroy(impl_.v_+impl_.vused_);
}
}
T& Top()
{
if (impl_.vused_ == 0)
{
throw "empty stack";
}
return impl_.v_[impl_.vused_-1];
}
private:
StackImpl<T> impl_;
};
说明:使用StackImpl封装内存管理,Stack对外提供接口实现。
如果没有特殊的要求,比如基类对象要优先初始化,或者覆盖基类的虚函数,优先使用最后一个组合的版本实现栈。
这两个使用了StackImpl版本的优点是:
对T的要求只有两个:(1)T的析构函数不抛异常;(2)T有copy constructor;
而第一个简单版本对T的要求:除上面二者外,还需要default constructor and Exception-safe 's copy assignment.
明显后续两个版本的实现对T的要求更少,更利于Stack容器的复用。
在C++标准库中的容器和迭代器而言,除了多元素插入不是强异常安全的,还有vector<T>,deque<T>不是的插入和删除不是强异常安全的,其余都是强异常安全的。
对于这两个例外,可以使用temp and swap的方式来实现。