• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            看到ATL中有3個類的代碼比較比較重復,在atlbase.h中,分別是CAutoVectorPtr, CAutoPtr和CAutoStackPtr,他們的功能其實很類似STL中的autoptr, 但是這里因為針對不同的分配對象而用了3個不同的類,其中CAutoVectorPtr是針對數(shù)組類型的,CAutoPtr是針對普通的非數(shù)組類型,而CAutoStackPtr針對的是_malloca分配的類型,因為最后釋放方式的不同,它這里用了3份代碼來實現(xiàn)。

            CAutoVectorPtr:
            template< typename T >
            class CAutoVectorPtr
            {
            public:
                CAutoVectorPtr() throw() :
                    m_p( NULL )
                {
                }
                CAutoVectorPtr( CAutoVectorPtr< T >& p ) throw()
                {
                    m_p = p.Detach();  // Transfer ownership
                }
                explicit CAutoVectorPtr( T* p ) throw() :
                    m_p( p )
                {
                }
                ~CAutoVectorPtr() throw()
                {
                    Free();
                }

                operator T*() const throw()
                {
                    return( m_p );
                }

                CAutoVectorPtr< T >& operator=( CAutoVectorPtr< T >& p ) throw()
                {
                    if(*this==p)
                    {
                        if(m_p == NULL)
                        {
                            // This branch means both two pointers are NULL, do nothing.
                        }
                        else if(this!=&p)
                        {
                            // If this assert fires, it means you attempted to assign one CAutoVectorPtr to another when they both contained 
                            
            // a pointer to the same underlying vector. This means a bug in your code, since your vector will get 
                            
            // double-deleted. 
                            ATLASSERT(FALSE);

                            // For safety, we are going to detach the other CAutoVectorPtr to avoid a double-free. Your code still
                            
            // has a bug, though.
                            p.Detach();
                        }
                        else
                        {
                            // Alternatively, this branch means that you are assigning a CAutoVectorPtr to itself, which is
                            
            // pointless but permissible

                            
            // nothing to do
                        }
                    }
                    else
                    {
                        Free();
                        Attach( p.Detach() );  // Transfer ownership
                    }
                    return( *this );
                }

                // basic comparison operators
                bool operator!=(CAutoVectorPtr<T>& p) const
                {
                    return !operator==(p);
                }

                bool operator==(CAutoVectorPtr<T>& p) const
                {
                    return m_p==p.m_p;
                }

                // Allocate the vector
                bool Allocate( size_t nElements ) throw()
                {
                    ATLASSUME( m_p == NULL );
                    ATLTRY( m_p = new T[nElements] );
                    if( m_p == NULL )
                    {
                        returnfalse );
                    }

                    returntrue );
                }
                // Attach to an existing pointer (takes ownership)
                void Attach( T* p ) throw()
                {
                    ATLASSUME( m_p == NULL );
                    m_p = p;
                }
                // Detach the pointer (releases ownership)
                T* Detach() throw()
                {
                    T* p;

                    p = m_p;
                    m_p = NULL;

                    return( p );
                }
                // Delete the vector pointed to, and set the pointer to NULL
                void Free() throw()
                {
                    delete[] m_p;
                    m_p = NULL;
                }

            public:
                T* m_p;
            };





            CAutoPtr:
            template< typename T >
            class CAutoPtr
            {
            public:
                CAutoPtr() throw() :
                    m_p( NULL )
                {
                }
                template< typename TSrc >
                CAutoPtr( CAutoPtr< TSrc >& p ) throw()
                {
                    m_p = p.Detach();  // Transfer ownership
                }
                CAutoPtr( CAutoPtr< T >& p ) throw()
                {
                    m_p = p.Detach();  // Transfer ownership
                }
                explicit CAutoPtr( T* p ) throw() :
                    m_p( p )
                {
                }
                ~CAutoPtr() throw()
                {
                    Free();
                }

                // Templated version to allow pBase = pDerived
                template< typename TSrc >
                CAutoPtr< T >& operator=( CAutoPtr< TSrc >& p ) throw()
                {
                    if(m_p==p.m_p)
                    {
                        // This means that two CAutoPtrs of two different types had the same m_p in them
                        
            // which is never correct
                        ATLASSERT(FALSE);
                    }
                    else
                    {
                        Free();
                        Attach( p.Detach() );  // Transfer ownership
                    }
                    return( *this );
                }
                CAutoPtr< T >& operator=( CAutoPtr< T >& p ) throw()
                {
                    if(*this==p)
                    {
                        if(this!=&p)
                        {
                            // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained 
                            
            // a pointer to the same underlying object. This means a bug in your code, since your object will get 
                            
            // double-deleted. 
            #ifdef ATL_AUTOPTR_ASSIGNMENT_ASSERT
                            ATLASSERT(FALSE);
            #endif

                            // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still
                            
            // has a bug, though.
                            p.Detach();
                        }
                        else
                        {
                            // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is
                            
            // pointless but permissible

                            
            // nothing to do
                        }
                    }
                    else
                    {
                        Free();
                        Attach( p.Detach() );  // Transfer ownership
                    }
                    return( *this );
                }

                // basic comparison operators
                bool operator!=(CAutoPtr<T>& p) const
                {
                    return !operator==(p);
                }

                bool operator==(CAutoPtr<T>& p) const
                {
                    return m_p==p.m_p;
                }

                operator T*() const throw()
                {
                    return( m_p );
                }
                T* operator->() const throw()
                {
                    ATLASSUME( m_p != NULL );
                    return( m_p );
                }

                // Attach to an existing pointer (takes ownership)
                void Attach( T* p ) throw()
                {
                    ATLASSUME( m_p == NULL );
                    m_p = p;
                }
                // Detach the pointer (releases ownership)
                T* Detach() throw()
                {
                    T* p;

                    p = m_p;
                    m_p = NULL;

                    return( p );
                }
                // Delete the object pointed to, and set the pointer to NULL
                void Free() throw()
                {
                    delete m_p;
                    m_p = NULL;
                }

            public:
                T* m_p;
            };

            CAutoStackPtr:
            /* Automatic cleanup for _malloca objects */
            template< typename T >
            class CAutoStackPtr
            {
            public:
                CAutoStackPtr() throw() :
                    m_p( NULL )
                {
                }
                template< typename TSrc >
                CAutoStackPtr( CAutoStackPtr< TSrc >& p ) throw()
                {
                    m_p = p.Detach();  // Transfer ownership
                }
                CAutoStackPtr( CAutoStackPtr< T >& p ) throw()
                {
                    m_p = p.Detach();  // Transfer ownership
                }
                explicit CAutoStackPtr( T* p ) throw() :
                    m_p( p )
                {
                }
                ~CAutoStackPtr() throw()
                {
                    Free();
                }

                // Templated version to allow pBase = pDerived
                template< typename TSrc >
                CAutoStackPtr< T >& operator=( CAutoStackPtr< TSrc >& p ) throw()
                {
                    if(m_p==p.m_p)
                    {
                        // This means that two CAutoPtrs of two different types had the same m_p in them
                        
            // which is never correct
                        ATLASSERT(FALSE);
                    }
                    else
                    {
                        Free();
                        Attach( p.Detach() );  // Transfer ownership
                    }
                    return( *this );
                }
                CAutoStackPtr< T >& operator=( CAutoStackPtr< T >& p ) throw()
                {
                    if(*this==p)
                    {
                        if(this!=&p)
                        {
                            // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained 
                            
            // a pointer to the same underlying object. This means a bug in your code, since your object will get 
                            
            // double-deleted. 
                            ATLASSERT(FALSE);

                            // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still
                            
            // has a bug, though.
                            p.Detach();
                        }
                        else
                        {
                            // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is
                            
            // pointless but permissible

                            
            // nothing to do
                        }
                    }
                    else
                    {
                        Free();
                        Attach( p.Detach() );  // Transfer ownership
                    }
                    return( *this );
                }

                // basic comparison operators
                bool operator!=(CAutoStackPtr<T>& p) const
                {
                    return !operator==(p);
                }

                bool operator==(CAutoStackPtr<T>& p) const
                {
                    return m_p==p.m_p;
                }

                operator T*() const throw()
                {
                    return( m_p );
                }
                T* operator->() const throw()
                {
                    ATLASSUME( m_p != NULL );
                    return( m_p );
                }

                // Attach to an existing pointer (takes ownership)
                void Attach( T* p ) throw()
                {
                    ATLASSUME( m_p == NULL );
                    m_p = p;
                }
                // Detach the pointer (releases ownership)
                T* Detach() throw()
                {
                    T* p;

                    p = m_p;
                    m_p = NULL;

                    return( p );
                }
                // Delete the object pointed to, and set the pointer to NULL
                void Free() throw()
                {
                    /* Note: _freea only actually does anything if m_p was heap allocated
                       If m_p was from the stack, it wouldn't be possible to actually free it here
                       [wrong function] unless we got inlined. But really all we do if m_p is 
                       stack-based is ignore it and let its alloca storage disappear at the end
                       of the outer function.
                    
            */
                    _freea(m_p);
                    m_p = NULL;
                }

            public:
                T* m_p;
            };

            可以看到上面代碼明顯非常重復,不知道ATL這樣寫是不是歷史原因,我們下面嘗試對它進行重構(gòu)。

            可以看到其實他們只是最終釋放(Free)的時候稍微有些差別,我們明顯可以把寫差別提取出來,作為一個釋放的Policy。

            struct DeleteFunctor
            {
                template<typename T> static void Release(T* p) { delete p; }
            };

            struct DeleteArrayFunctor
            {
                template<typename T> static void Release(T* p) { delete []p; }
            };

            struct DeleteStackFunctor
            {
                template<typename T> static void Release(T* p) { _freea p; }
            };

            然后我們把上面的各種釋放行為作為一個模板參數(shù)傳進去就可以了,代碼如下:
            template< typename T, typename ReleasePolicy>
            class CAutoReleasePtr
            {
            public:
                CAutoReleasePtr() throw() :
                  m_p( NULL )
                  {
                  }
                  template< typename TSrc >
                  CAutoReleasePtr( CAutoReleasePtr< TSrc >& p ) throw()
                  {
                      m_p = p.Detach();  // Transfer ownership
                  }
                  CAutoReleasePtr( CAutoReleasePtr< T >& p ) throw()
                  {
                      m_p = p.Detach();  // Transfer ownership
                  }
                  explicit CAutoReleasePtr( T* p ) throw() :
                  m_p( p )
                  {
                  }
                  ~CAutoReleasePtr() throw()
                  {
                      Free();
                  }

                  // Templated version to allow pBase = pDerived
                  template< typename TSrc >
                  CAutoReleasePtr< T >& operator=( CAutoReleasePtr< TSrc >& p ) throw()
                  {
                      if(m_p==p.m_p)
                      {
                          // This means that two CAutoPtrs of two different types had the same m_p in them
                          
            // which is never correct
                          ATLASSERT(FALSE);
                      }
                      else
                      {
                          Free();
                          Attach( p.Detach() );  // Transfer ownership
                      }
                      return( *this );
                  }
                  CAutoReleasePtr< T >& operator=( CAutoReleasePtr< T >& p ) throw()
                  {
                      if(*this==p)
                      {
                          if(this!=&p)
                          {
                              // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained 
                              
            // a pointer to the same underlying object. This means a bug in your code, since your object will get 
                              
            // double-deleted. 
            #ifdef ATL_AUTOPTR_ASSIGNMENT_ASSERT
                              ATLASSERT(FALSE);
            #endif

                              // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still
                              
            // has a bug, though.
                              p.Detach();
                          }
                          else
                          {
                              // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is
                              
            // pointless but permissible

                              
            // nothing to do
                          }
                      }
                      else
                      {
                          Free();
                          Attach( p.Detach() );  // Transfer ownership
                      }
                      return( *this );
                  }

                  // basic comparison operators
                  bool operator!=(CAutoReleasePtr<T>& p) const
                  {
                      return !operator==(p);
                  }

                  bool operator==(CAutoReleasePtr<T>& p) const
                  {
                      return m_p==p.m_p;
                  }

                  operator T*() const throw()
                  {
                      return( m_p );
                  }
                  T* operator->() const throw()
                  {
                      ATLASSUME( m_p != NULL );
                      return( m_p );
                  }

                  // Attach to an existing pointer (takes ownership)
                  void Attach( T* p ) throw()
                  {
                      ATLASSUME( m_p == NULL );
                      m_p = p;
                  }
                  // Detach the pointer (releases ownership)
                  T* Detach() throw()
                  {
                      T* p;

                      p = m_p;
                      m_p = NULL;

                      return( p );
                  }
                  // Delete the object pointed to, and set the pointer to NULL
                  void Free() throw()
                  {
                      ReleasePolicy::Release(m_p);
                      m_p = NULL;
                  }

            public:
                T* m_p;
            };

            可以看到我們上面其實就改了一行代碼,改了下最終的釋放策略.

            好,現(xiàn)在我們可以這樣用了:
            CAutoReleasePtr<T, DeleteFunctor> p1(new int);
            CAutoReleasePtr<T, DeleteArrayFunctor> p2(new int[10]);
            功能是可以了,但是是不是覺得上面這樣用起來不方便,typedef一下就好了:
             typedef CAutoReleasePtr<T, DeleteFunctor> CSimplePtr<T>;
             typedef CAutoReleasePtr<T, DeleteArrayFunctor> CArrayPtr<T>;
             typedef CAutoReleasePtr<T, DeleteStackFunctor> CStackPtr<T>;
            但是我們很塊發(fā)現(xiàn)上面的代碼編譯都過不了。

            既然typedef不行,那我們就通過繼承來生成一個新類:
            template<typename T> class CSimplePtr: public CAutoReleasePtr<T, DeleteFunctor> {};
            template<typename T> class CArrayPtr: public CAutoReleasePtr<T, DeleteArrayFunctor> {};
            template<typename T> class CStackPtr: public CAutoReleasePtr<T, DeleteStackFunctor> {};
            我們很快又發(fā)現(xiàn),用不起來,我們新類的構(gòu)造函數(shù)需要重寫才行。

            接下來我們考慮生成一個新類,然后在內(nèi)部typedef:
             template<typename T>
             struct CSimplePtr
             {
                 typedef CAutoReleasePtr<T, DeleteFunctor> type;
             };
             
             template<typename T>
             struct CArrayPtr
             {
                 typedef CAutoReleasePtr<T, DeleteArrayFunctor> type;
             };
             
             template<typename T>
             struct CStackPtr
             {
                 typedef CAutoReleasePtr<T, DeleteStackFunctor> type;
             };
            然后這樣用:
            CSimplePtr<int>::type p(new int);
            CArrayPtr<int>::type p1(new int[20]);
            可是這樣用和最初的用法似乎又沒多少改進....

            再最后想到了用宏:
            #define CSimplePtr(T) CAutoReleasePtr<T, DeleteFunctor>
            #define CArrayPtr(T) CAutoReleasePtr<T, DeleteArrayFunctor>
            但是用的時候太嘔心了:
            CSimplePtr(int) p(new int);
            CArrayPtr(int) p1(new int[20]);

            最后,實在沒有什么辦法了....
            不知道大家有沒有什么好方法 ???

            posted on 2012-09-24 22:59 Richard Wei 閱讀(1899) 評論(4)  編輯 收藏 引用 所屬分類: C++

            FeedBack:
            # re: 重構(gòu)ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr
            2012-09-25 07:33 | 萬連文
            C++03標準下最推薦的是CSimplePtr<int>::type p(new int);這種

            http://en.wikipedia.org/wiki/C%2B%2B0x#Alias_templates 支持c++11可以這樣

            貌似只能如此,不必太過糾結(jié)啊  回復  更多評論
              
            # re: 重構(gòu)ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr
            2012-09-25 08:36 | Richard Wei
            @萬連文
            確實,C++11里把這個叫住Alias templates  回復  更多評論
              
            # re: 重構(gòu)ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr[未登錄]
            2012-09-25 10:56 | 春秋十二月
            1) CAutoReleasePtr的一些成員函數(shù)的參數(shù)少了ReleasePolicy,例如下:
            template<typename TSrc>
            CAutoReleasePtr(CAutoReleasePtr<TSrc,ReleasePolicy>& p)throw()
            {
            m_p = p.Detach(); // Transfer ownership
            }
            CAutoReleasePtr( CAutoReleasePtr<T,ReleasePolicy>& p ) throw()
            {
            m_p = p.Detach(); // Transfer ownership
            }

            2) 可以定義一個公共方法的宏來減少代碼重復,但缺點是不利于調(diào)試。例如下:
            template<T>
            class CSimplePtr
            {
            COMMON_MEMBER_METHOD(T)
            void Free() { delete m_p; }
            private:
            T* m_p;
            }
            template<T>
            class CArrayPtr
            {
            COMMON_MEMBER_METHOD(T)
            void Free() { delete []m_p; }
            private:
            T* m_p;
            }
            template<T>
            class CStatckPtr
            {
            COMMON_MEMBER_METHOD(T)
            void Free() { _freea m_p; }
            private:
            T* m_p;
            }

            3)模板和宏的共同點是都能避免重復代碼,但模板更優(yōu)越,這也是C++相對C進步的表現(xiàn)。

            4)c++11新標準支持帶模板參數(shù)的typedef,又是一個進步。  回復  更多評論
              
            # re: 重構(gòu)ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr
            2012-09-25 11:21 | Richard Wei
            @春秋十二月
            多謝,總結(jié)的挺好  回復  更多評論
              
            久久精品亚洲日本波多野结衣| 久久久久四虎国产精品| 亚洲精品NV久久久久久久久久 | 久久这里只有精品久久| 久久综合丁香激情久久| 中文字幕无码久久久| 国内精品九九久久久精品| 久久国产精品免费| 久久精品人人做人人爽97| 久久人人爽人人爽人人片AV麻豆 | 国内精品久久久久伊人av| 久久国产免费直播| 久久国产精品99精品国产| 人妻丰满?V无码久久不卡| 99re这里只有精品热久久| 久久久久se色偷偷亚洲精品av| 国产激情久久久久影院| 国产精品久久免费| 久久婷婷五月综合97色一本一本| 中文精品99久久国产| 欧美久久久久久午夜精品| 国产精品久久久久无码av| 无码国内精品久久人妻蜜桃 | 中文字幕精品无码久久久久久3D日动漫| 久久久国产乱子伦精品作者| 久久强奷乱码老熟女网站| 亚洲欧洲精品成人久久曰影片| 国产精品久久久久久久| 亚洲精品乱码久久久久久蜜桃图片| 热久久国产欧美一区二区精品| 久久五月精品中文字幕| 国产一区二区三精品久久久无广告| 亚洲狠狠久久综合一区77777| 久久精品国产亚洲AV无码娇色| 日产精品99久久久久久| 久久综合亚洲欧美成人| 日日躁夜夜躁狠狠久久AV| 丁香五月网久久综合| 亚洲午夜久久影院| 久久人妻少妇嫩草AV无码蜜桃| 免费久久人人爽人人爽av|