zoukankan      html  css  js  c++  java
  • 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++有两个要求:

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

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

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

  • 相关阅读:
    设计模式03-工厂方法
    设计模式02-抽象工厂
    设计模式01-什么是设计模式
    工作流activiti-03数据查询(流程定义 流程实例 代办任务) 以及个人小练习
    工作流activiti-02事物控制、流程引擎创建
    工作流activiti-01个人小结
    jQuery.extend 函数详解
    hibernate框架学习之数据查询(QBC)
    hibernate框架学习之多表查询helloworld
    hibernate框架学习之数据查询(HQL)helloworld
  • 原文地址:https://www.cnblogs.com/pugang/p/2662104.html
Copyright © 2011-2022 走看看