ATL Internals 2ed复习.chapter 3.CAutoPtr

来源:互联网 发布:绿坝花季护航软件 编辑:程序博客网 时间:2024/05/29 16:23

ATL提供了CAutoPtr, CAutoVectorPtr, CAutoPtrArray, and CAutoPtrList,它们具有类似auto_ptr功能,而没有抛出异常,并且不需要借助于CRT库。

The CAutoPtr and CAutoVectorPtr Classes

例子:

 

STDMETHODIMP CMyClass::SomeFunc() {    CFoo* pFoo = new Foo();        // instantiate C++ class    CAutoPtr<CFoo> spFoo(pFoo);    // take ownership of pFoo    spFoo->DoSomeFoo();    // ... do other things with spFoo}   // CAutoPtr deletes pFoo instance    // when spFoo goes out of scope

下面以CAutoPtr为样板,其他智能指针功能类似

Constructors and Destructor

 

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


注意4th类型,p可以为派生类

class CAnimal { ... };class CDog : public CAnimal { ... };//...CDog* pDog = new CDog();CAutoPtr<CAnimal> spAnimal(pDog);


 

~CAutoPtr()  {                    Free();                    }                              void Free()  {                     delete m_p;                     m_p = NULL;                }                              


 

CAutoPtr Operators

 

template< typename TSrc >                          CAutoPtr< T >& operator=( CAutoPtr< TSrc >& p ) {      if(m_p==p.m_p) {                                       ATLASSERT(FALSE);                              } else {                                               Free();                                            Attach( p.Detach() ); // Transfer ownership    }                                                  return( *this );                               }                                                                                                     CAutoPtr< T >& operator=( CAutoPtr< T >& p ) {         if(*this==p) {                                         if(this!=&p) {                                         ATLASSERT(FALSE);                                  p.Detach();                                    } else {                                           }                                              } else {                                               Free();                                            Attach( p.Detach() ); // Transfer ownership    }                                                  return( *this );                               }                                                  

不管采用何种形态,首先检查指针是否指向同一个实例,然后Free(),再用Detach()转移释放权,避免多次delete
注意第一种形态,TSrc可以为T的衍生类,例子:

class CAnimal { ... };class CDog : public CAnimal { ... };// ...// instantiate a CAnimalCAutoPtr<CAnimal> spAnimal(new CAnimal());// instantiate a CDogCAutoPtr<CDog> spDog(new CDog());// CAnimal instance freed herespAnimal = spDog;// ... CDog instance will be freed when spAnimal// goes out of scope


类重新定义了->操作:

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


例子:

class CDog {public:    void Bark() {}    int m_nAge;};CAutoPtr<CDog> spDog(new Dog);spDog->Bark();spDog->m_nAge += 5;

比较操作符:

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



 CAutoVectorPtr

和CAutoPtr相比,有多点不同:

CAutoVectorPtr不能使用派生类指针进行赋值

CAutoVectorPtr使用Allocate进行集合构造,类似于new[]:

bool Allocate( size_t nElements ) {      ATLASSERT( m_p == NULL );            ATLTRY( m_p = new T[nElements] );    if( m_p == NULL ) {                      return( false );                 }                                                                         return( true );                  }                                    

例子:

class CAnimal { public: void Growl() {} };// each instance is of type CAnimalCAutoVectorPtr<CAnimal> spZoo;// allocate and initialize 100 CAnimal'sspZoo.Allocate(100);


注意,该类没有重载->操作符,所以下面的代码是错误的:

spZoo->Growl();    // wrong! can't do this => doesn't make sense


而且,ATL并没有重载operator[],所以必须要使用下面的形式:

((CAnimal*)spZoo)[5].Growl();


而且,ATL只接受带有默认构造函数的类,所以下面的代码是错误的:

class CAnimal {public:CAnimal(int nAge) : m_nAge(nAge) {}        void Growl() {}private:int m_nAge;}CAutoVectorPtr<CAnimal> spZoo;spZoo.Allocate(100); // won't compile => no default constructor

注意,析构函数使用了delete[]来释放内存,对应的只能是Allocate(),所以如果用户使用了Attach(),就会造成麻烦:

class CAnimal {};// allocate only a single instanceCAnimal* pAnimal = new Animal;CAutoVectorPtr<CAnimal> spZoo;// wrong, wrong!!! pAnimal is not a collectionspZoo.Attach(pAnimal)




 

 

原创粉丝点击