ATL智能指针类剖析

 

CComPtr

    CComPtr派生自模板类CComPtrBase<T>,T代表某个COM接口。CComPtrBase<T>类只有一个成员变量T* p。下面是它们的代码分析:

 

 

构造函数

protected:
    CComPtrBase() throw()
    {
        p = NULL;
    }
    CComPtrBase(_In_ int nNull) throw()
    {
        ATLASSERT(nNull == 0);
        (void)nNull;
        p = NULL;
    }
    CComPtrBase(_In_opt_ T* lp) throw()
    {
        p = lp;
        if (p != NULL)
            p->AddRef();
    }

    构造函数都被限定为protected,这样保证了无法直接创建CComPtrBase<T>对象,必须有子类的构造函数来调用它们。默认构 造函数和整数0作为参数的构造函数将p初始化为NULL。第三种形式会保存外部接口指针给p,并调用AddRef。

    CComPtrBase没有提供AddRef成员函数供外部使用,为了生命周期一致,这是必要的。所以也不要通过operator->来调用内部p的AddRef方法。

 

    CComPtr<T>增加了拷贝构造函数:

CComPtr(_In_ const CComPtr<T>& lp) throw() :
        CComPtrBase<T>(lp.p)
    {
    }

    本质上还是调用基类的第三种构造函数,因此也会调用p->AddRef方法。

 

析构函数

public:
    ~CComPtrBase() throw()
    {
        if (p)
            p->Release();
    }

 

    注意析构函数没有virtual关键字,按照我们通常的认识,一个类如果被设计成被别的类继承,它需要一个虚析构函数,但是这里没有。为什么呢?因为它的子类CComPtr<T>没有任何成员变量,因此当我们如下调用的时候,并不会造成内存泄露。

    CComPtrBase<IUnknown>* p=new CComPtr<IUnknown>();
    delete p;

    但是,这并不是一个很好的方法,虽然看似这里省了点虚函数调用的开销,但是谁又能保证不会有哪个人突然自己创造了一个 CComPtrBase<T>的子类,然后加了很多自己的成员变量,而如果他没有看过CComPtrBase<T>的代码,结果 会怎么样?我认为这的确是个设计不良!

    析构函数保证了退栈的时候,如果p不为NULL,则会被调用接口的Release函数。CComPtr<T>没有提供析构函数,由于没有成员变量拥有析构函数,父类也没有虚析构函数,所以编译器也不会生成默认析构函数。

Release

    作为一个原则,要记住的是我们总应该调用CComPtrBase::Release,而不是通过operator ->获得的接口指针来调用Release方法。为什么呢?再看看上面的代码,析构函数在p不为NULL不为的时候,会调用Release。如果我们 直接通过->来调用Release,我们又忘记将成员变量p设置为NULL设置为的话,那么析构函数会进行第二次Release调用,结果当然会导 致错误。下面是可靠地CComPtrBase::Release方法的代码:
    void Release() throw()
    {
        T* pTemp = p;
        if (pTemp)
        {
            p = NULL;
            pTemp-

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值