• <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是針對數組類型的,CAutoPtr是針對普通的非數組類型,而CAutoStackPtr針對的是_malloca分配的類型,因為最后釋放方式的不同,它這里用了3份代碼來實現。

            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這樣寫是不是歷史原因,我們下面嘗試對它進行重構。

            可以看到其實他們只是最終釋放(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; }
            };

            然后我們把上面的各種釋放行為作為一個模板參數傳進去就可以了,代碼如下:
            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;
            };

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

            好,現在我們可以這樣用了:
            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>;
            但是我們很塊發現上面的代碼編譯都過不了。

            既然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> {};
            我們很快又發現,用不起來,我們新類的構造函數需要重寫才行。

            接下來我們考慮生成一個新類,然后在內部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 閱讀(1890) 評論(4)  編輯 收藏 引用 所屬分類: C++

            FeedBack:
            # re: 重構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可以這樣

            貌似只能如此,不必太過糾結啊  回復  更多評論
              
            # re: 重構ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr
            2012-09-25 08:36 | Richard Wei
            @萬連文
            確實,C++11里把這個叫住Alias templates  回復  更多評論
              
            # re: 重構ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr[未登錄]
            2012-09-25 10:56 | 春秋十二月
            1) CAutoReleasePtr的一些成員函數的參數少了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) 可以定義一個公共方法的宏來減少代碼重復,但缺點是不利于調試。例如下:
            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)模板和宏的共同點是都能避免重復代碼,但模板更優越,這也是C++相對C進步的表現。

            4)c++11新標準支持帶模板參數的typedef,又是一個進步。  回復  更多評論
              
            # re: 重構ATL中的CAutoVectorPtr, CAutoPtr和CAutoStackPtr
            2012-09-25 11:21 | Richard Wei
            @春秋十二月
            多謝,總結的挺好  回復  更多評論
              
            久久免费视频一区| 亚洲国产一成人久久精品| 亚洲精品tv久久久久久久久| 国产高潮久久免费观看| 久久美女人爽女人爽| 国产成人精品免费久久久久| 国色天香久久久久久久小说| 久久久午夜精品| 欧美日韩精品久久久免费观看| 国产精品免费久久| 久久久久无码国产精品不卡| 亚洲国产天堂久久综合网站| 免费观看久久精彩视频| 国产AV影片久久久久久| 久久久精品人妻无码专区不卡| 国产综合成人久久大片91| 久久久久无码精品| 一日本道伊人久久综合影| 久久久精品久久久久影院| 久久九九兔免费精品6| 国产精品久久午夜夜伦鲁鲁| 国产精品一久久香蕉国产线看| 国产精品视频久久久| 久久精品夜色噜噜亚洲A∨| 国产精品99久久久精品无码| 亚洲国产另类久久久精品小说 | 亚洲欧洲精品成人久久奇米网| 久久精品免费网站网| 久久乐国产综合亚洲精品| 国产综合久久久久久鬼色| 国产精品成人精品久久久| 国产精品中文久久久久久久| 精品国际久久久久999波多野| 久久婷婷综合中文字幕| 久久人人爽人人爽人人片AV高清 | 久久久久夜夜夜精品国产| 久久婷婷五月综合色99啪ak| 人妻久久久一区二区三区| 国产精品久久永久免费| 久久精品国产亚洲AV不卡| 久久综合中文字幕|