Exceptional C++ 精华代码—实现异常安全的Stack

Exceptional C++ 精华代码实现异常安全的Stack

最近赶上15号台风过境,意外的休息了半天,于是重新读了一遍Exceptional C++,在网上找了一下书中关于实现异常安全的Stack的代码,但是基本上都组织的有些乱,于是将其整理一下,并加以自己的注释,希望对学习C++的朋友们有所帮助。

首先关于这段代码是以分离实现的方式组织的,真正的实现代码和接口类分离,首先是StackImpl实现,所有的内存操作相关的工作都移到这个类中实现的:

--Separate Implementation class---Implementation of StackImpl--

template <class T> class StackImpl

{

                        public :

                        StackImpl ( size_t size = 0 );

                        ~ StackImpl ();

                        void Swap ( StackImpl & other ) throw ();

                        T* v_; // ptr to dynamic memory area

                        size_t vsize_ ; // capacity of v_

                        size_t vused_ ; // # of T's actually in use

                        private :

                        // private and undefined : no copying allowed

                        StackImpl ( const StackImpl & );

                        StackImpl & operator =( const StackImpl & );

};

 

构造函数和析构函数实现如下:

Constructor:

template <class T>

StackImpl <T >:: StackImpl ( size_t size )

: v_( static_cast <T*>

( size == 0 ? 0: operator new( sizeof (T)* size ) ) ),

vsize_ ( size ),

vused_ ( 0 )

{

}

 

Destructor:

template <class T>

StackImpl <T >::~ StackImpl ()

{

                        destroy ( v_ , v_+ vused_ );

                        operator delete ( v_ );

}

 

工具函数实现如下:

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 FwdIt > void destroy ( FwdIt first , FwdIt last )

{

                        while ( first != last )

                        {

                                                destroy ( &* first );

                                                ++ first ;

                        }

}

 

template <class T>

void StackImpl <T >:: Swap ( StackImpl & other ) throw ()

{

                        swap ( v_ , other .v_ );

                        swap ( vsize_ , other . vsize_ );

                        swap ( vused_ , other . vused_ );

}

 

template <class T> void swap ( T& a, T& b )

{

            T temp (a);

a = b;

b = temp ;

}

Swap() safely exchanges guts of a StackImpl object with another one This cannot throw (only assignment of pointers)!

 

真正的Stack实现代码如下, StackImpl作为Stack的成员出现:

--Separate Implementation class---Implementation of Stack--

Stack containing StackImpl member

template <class T> class Stack

{

                        public :

                        Stack ( size_t size = 0 );

                        ~ Stack ();

                        Stack ( const Stack & );

                        Stack & operator =( const Stack & );

                        size_t Count () const ;

                        void Push ( const T& );

                        T& Top (); // if empty , throws exception

                        void Pop (); // if empty , throws exception

                        private :

                        StackImpl <T> impl_ ; // private implementation

};

Stack in HAS-A containment relationship to StackImpl

Alternative: Private inheritance (StackImpl's interface could be protected in this case)

 

构造函数,拷贝构造函数和拷贝复制函数实现如下:

Constructor

template <class T> Stack <T >:: Stack ( size_t size =0)

: impl_ ( size )

{

}

 

Copy Constructor:

 template <class T> Stack <T >:: Stack ( const Stack <T >& other )

 : impl_ ( other . impl_ . vused_ )

 {

                         while ( impl_ . vused_ < other . impl_ . vused_ )

                         {

                                                 construct ( impl_ .v_+ impl_ .vused_ , other . impl_ .v_[ impl_ . vused_ ]);

                                                 ++ impl_ . vused_ ;

                         }

 }

 

Copy Assignment

template <class T>

Stack <T >& Stack <T >:: operator =( const Stack <T >& other )

{

                        Stack <T> temp ( other );

                        impl_ . Swap ( temp . imp_ ); // this can 't throw

                        return * this ;

}

Canonical form of copy assignment:"Create Temporary and Swap"idiom Strongly exception safe, provided non-throwing Swap() function Protected against self-assignment.Take code that might throw safely off to the side. When this has succeeded, modify the program state (and clean up) using only non-throwing operations.

 

计数函数实现如下:

template <class T>

size_t Stack <T >:: Count () const

{

                        return impl_ . vused_ ;

}

 

Push操作实现如下:

template <class T>

size_t Stack <T >:: Push ( const T& t )

{

                        if ( impl_ . vused_ == impl_ . vsize_ ) {

                        Stack temp ( impl_ . vsize_ * 2 + 1 );

                        while ( temp . Count () < impl_ . vsize_ )

                        {

                                                temp . Push ( impl_ .v_[ temp . Count ()] );

                        }

                        temp . Push ( t );

                        impl_ . Swap ( temp . impl_ );

                        }

                        else

                        {

                                                                        construct ( impl_ .v_ + impl_ .vused_ , t );

                                                                        ++ impl_ . vused_ ;

                        }

}

 

Pop操作实现如下:

template <class T> std :: auto_ptr <T> Stack <T >:: Pop ()

{

                         if ( impl_ . vused_ == 0 ) throw " empty stack ";

                         std :: auto_ptr <T> res = new T( impl_ .v_[ impl_ . vused_ - 1] );

                         --impl_ . vused_ ;

                         destroy ( impl_ .v_ + impl_ . vused_ );

                         return res;

}

auto_ptr assignment cannot failTrades off performance for exception safety.

 

总结

编写异常安全的C++代码的关键在于了解什么是异常安全的代码,以及什么时候可以抛出异常,什么时候不要抛异常,在这一点上C++C#有很大区别,不要想当然!

对于C++有两个要求:

对于处理不了的异常要向外层抛出,不能随意丢弃。

对于发生异常的情况下,不应该有资源泄漏或者状态不一致。

希望本文对大家有所帮助。

原文地址:https://www.cnblogs.com/pugang/p/2662104.html