ATL Internals 2ed复习.chapter 3.CAutoPtr

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 CAnimal
CAutoPtr<CAnimal> spAnimal(new CAnimal());

// instantiate a CDog
CAutoPtr<CDog> spDog(new CDog());
// CAnimal instance freed here
spAnimal = 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 CAnimal
CAutoVectorPtr<CAnimal> spZoo;
// allocate and initialize 100 CAnimal's
spZoo.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 instance
CAnimal* pAnimal = new Animal;
CAutoVectorPtr<CAnimal> spZoo;
// wrong, wrong!!! pAnimal is not a collection
spZoo.Attach(pAnimal)




 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值