智能指针之句柄类

对于上一篇提到的方法,可以不用引入辅助类,可以直接把指针封装起来。然后,重载操作符,定义为一个指针的行为,使得可以像使用指针一样使用它。这种方法叫做句柄类,查下了资料,对这个的解释是存储指向动态分配对象指针的类。可以在适当的时间自动删除指向的对象,同时,它的行为也像一个指针。由此可以看出本文标题不太合适。

同样的先上一张图。


1.定义一个SmartPtr对象P1,传入实际指针对象,调用构造函数,初始化计数为1;
2.定义一个SmartPtr对象P2,调用拷贝构造函数,此时,P1和P2的ptr指向相同的地址,pUse指向相同的地址,引用计数自加;
3.定义一个SmartPtr对象P3,调用赋值,操作符右操作数引用计数自加,左操作数自减,并判断原引用计数是否为0,如果是0,则删除原ptr指针指向的地址内容,赋值ptr和pUse,指向相同的ptr和pUse
4.析构时,引用计数自减,并判断计数值是否为0,如果是0,则自动删除指针对象。

示例代码如下:

template<typename T>
class SmartPtr
{
public:
	SmartPtr(T* p= 0)
		:ptr(p),pUse(new size_t(1))
	{}

	~SmartPtr()
	{
		decrUse();
	}

	SmartPtr(const SmartPtr<T>& src)
		:ptr(src.ptr),pUse(src.pUse)
	{
		++*pUse;
	}

	SmartPtr<T>& operator=(const SmartPtr<T>& rhs)
	{
		if (rhs.ptr != ptr)
		{
			++*rhs.pUse;
			decrUse();
			ptr = rhs.ptr;
			pUse = rhs.pUse;
		}
		return *this;
	}

	T* operator->()
	{
		if(ptr)
			return ptr;
		throw std::runtime_error("access through NULL pointer");
	}

	const T* operator->() const
	{
		if(ptr)
			return ptr;
		throw std::runtime_error("access through NULL pointer");
	}

	T& operator*()
	{
		if(ptr)
			return *ptr;
		throw std::runtime_error("dereference of NULL pointer");
	}

	const T& operator*() const
	{
		if(ptr)
			return *ptr;
		throw std::runtime_error("dereference of NULL pointer");
	}

private:

	void decrUse()
	{
		if(--*pUse == 0)
		{
			delete ptr;
			delete pUse;
		}
	}

private:
	T* ptr;
	size_t* pUse;
};
顺便贴上一点Cocos2d的智能指针类的代码,它使用的方式是引入辅助类,辅助类里有引用计数,当然这个辅助类不仅限于在智能指针的使用。省略一部分代码和注释。
class CC_DLL Ref
{
public:
    void retain();
    void release();
    Ref* autorelease();
    unsigned int getReferenceCount() const;

protected:
    Ref();

public:
    virtual ~Ref();

protected:
    /// count of references
    unsigned int _referenceCount;

    friend class AutoreleasePool;

    // Memory leak diagnostic data (only included when CC_USE_MEM_LEAK_DETECTION is defined and its value isn't zero)
#if CC_USE_MEM_LEAK_DETECTION
public:
    static void printLeaks();
#endif
};

下面是RefPtr,Cocos2d的智能指针类

template <typename T> class RefPtr
{
public:
    
    inline RefPtr()
    :
        _ptr(nullptr)
    {
        
    }
    
    inline RefPtr(RefPtr<T> && other)
    {
        _ptr = other._ptr;
        other._ptr = nullptr;
    }

    inline RefPtr(T * ptr)
    :
        _ptr(const_cast<typename std::remove_const<T>::type*>(ptr))     // Const cast allows RefPtr<T> to reference objects marked const too.
    {
        CC_REF_PTR_SAFE_RETAIN(_ptr);
    }
    
    inline RefPtr(std::nullptr_t ptr)
    :
        _ptr(nullptr)
    {
        
    }
    
    inline RefPtr(const RefPtr<T> & other)
    :
        _ptr(other._ptr)
    {
        CC_REF_PTR_SAFE_RETAIN(_ptr);
    }
    
    inline ~RefPtr()
    {
        CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
    }
    
    inline RefPtr<T> & operator = (const RefPtr<T> & other)
    {
        if (other._ptr != _ptr)
        {
            CC_REF_PTR_SAFE_RETAIN(other._ptr);
            CC_REF_PTR_SAFE_RELEASE(_ptr);
            _ptr = other._ptr;
        }
        
        return *this;
    }
    
    inline RefPtr<T> & operator = (RefPtr<T> && other)
    {
        if (&other != this)
        {
            CC_REF_PTR_SAFE_RELEASE(_ptr);
            _ptr = other._ptr;
            other._ptr = nullptr;
        }
        
        return *this;
    }
    
    inline RefPtr<T> & operator = (T * other)
    {
        if (other != _ptr)
        {
            CC_REF_PTR_SAFE_RETAIN(other);
            CC_REF_PTR_SAFE_RELEASE(_ptr);
            _ptr = const_cast<typename std::remove_const<T>::type*>(other);     // Const cast allows RefPtr<T> to reference objects marked const too.
        }
        
        return *this;
    }
    
    inline RefPtr<T> & operator = (std::nullptr_t other)
    {
        CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
        return *this;
    }
    
    // Note: using reinterpret_cast<> instead of static_cast<> here because it doesn't require type info.
    // Since we verify the correct type cast at compile time on construction/assign we don't need to know the type info
    // here. Not needing the type info here enables us to use these operations in inline functions in header files when
    // the type pointed to by this class is only forward referenced.
    
    inline operator T * () const { return reinterpret_cast<T*>(_ptr); }
    
    inline T & operator * () const
    {
        CCASSERT(_ptr, "Attempt to dereference a null pointer!");
        return reinterpret_cast<T&>(*_ptr);
    }
    
    inline T * operator->() const
    {
        CCASSERT(_ptr, "Attempt to dereference a null pointer!");
        return reinterpret_cast<T*>(_ptr);
    }
    
    inline T * get() const { return reinterpret_cast<T*>(_ptr); }
    
    
    inline bool operator == (const RefPtr<T> & other) const { return _ptr == other._ptr; }
    
    inline bool operator == (const T * other) const { return _ptr == other; }
    
    inline bool operator == (typename std::remove_const<T>::type * other) const { return _ptr == other; }
    
    inline bool operator == (const std::nullptr_t other) const { return _ptr == other; }
    
    
    inline bool operator != (const RefPtr<T> & other) const { return _ptr != other._ptr; }
    
    inline bool operator != (const T * other) const { return _ptr != other; }
    
    inline bool operator != (typename std::remove_const<T>::type * other) const { return _ptr != other; }
    
    inline bool operator != (const std::nullptr_t other) const { return _ptr != other; }
    
    
    inline bool operator > (const RefPtr<T> & other) const { return _ptr > other._ptr; }
    
    inline bool operator > (const T * other) const { return _ptr > other; }
    
    inline bool operator > (typename std::remove_const<T>::type * other) const { return _ptr > other; }
    
    inline bool operator > (const std::nullptr_t other) const { return _ptr > other; }
    
    
    inline bool operator < (const RefPtr<T> & other) const { return _ptr < other._ptr; }
    
    inline bool operator < (const T * other) const { return _ptr < other; }
    
    inline bool operator < (typename std::remove_const<T>::type * other) const { return _ptr < other; }
    
    inline bool operator < (const std::nullptr_t other) const { return _ptr < other; }
    
        
    inline bool operator >= (const RefPtr<T> & other) const { return _ptr >= other._ptr; }
    
    inline bool operator >= (const T * other) const { return _ptr >= other; }
    
    inline bool operator >= (typename std::remove_const<T>::type * other) const { return _ptr >= other; }
    
    inline bool operator >= (const std::nullptr_t other) const { return _ptr >= other; }
    
        
    inline bool operator <= (const RefPtr<T> & other) const { return _ptr <= other._ptr; }
    
    inline bool operator <= (const T * other) const { return _ptr <= other; }
    
    inline bool operator <= (typename std::remove_const<T>::type * other) const { return _ptr <= other; }
    
    inline bool operator <= (const std::nullptr_t other) const { return _ptr <= other; }
    
        
    inline operator bool() const { return _ptr != nullptr; }
        
    inline void reset()
    {
        CC_REF_PTR_SAFE_RELEASE_NULL(_ptr);
    }
        
    inline void swap(RefPtr<T> & other)
    {
        if (&other != this)
        {
            Ref * tmp = _ptr;
            _ptr = other._ptr;
            other._ptr = tmp;
        }
    }
    
    /**
     * This function assigns to this RefPtr<T> but does not increase the reference count of the object pointed to.
     * Useful for assigning an object created through the 'new' operator to a RefPtr<T>. Basically used in scenarios
     * where the RefPtr<T> has the initial ownership of the object.
     *
     * E.G:
     *      RefPtr<cocos2d::Image> image;
     *      image.weakAssign(new cocos2d::Image());
     *
     * Instead of:
     *      RefPtr<cocos2d::Image> image;
     *      image = new cocos2d::Image();
     *      image->release();               // Required because new'd object already has a reference count of '1'.
     */
    inline void weakAssign(const RefPtr<T> & other)
    {
        CC_REF_PTR_SAFE_RELEASE(_ptr);
        _ptr = other._ptr;
    }
    
private:
    Ref * _ptr;
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值