智能指针之句柄类
2014-09-01 21:07
190 查看
对于上一篇提到的方法,可以不用引入辅助类,可以直接把指针封装起来。然后,重载操作符,定义为一个指针的行为,使得可以像使用指针一样使用它。这种方法叫做句柄类,查下了资料,对这个的解释是存储指向动态分配对象指针的类。可以在适当的时间自动删除指向的对象,同时,它的行为也像一个指针。由此可以看出本文标题不太合适。
同样的先上一张图。
1.定义一个SmartPtr对象P1,传入实际指针对象,调用构造函数,初始化计数为1;
2.定义一个SmartPtr对象P2,调用拷贝构造函数,此时,P1和P2的ptr指向相同的地址,pUse指向相同的地址,引用计数自加;
3.定义一个SmartPtr对象P3,调用赋值,操作符右操作数引用计数自加,左操作数自减,并判断原引用计数是否为0,如果是0,则删除原ptr指针指向的地址内容,赋值ptr和pUse,指向相同的ptr和pUse
4.析构时,引用计数自减,并判断计数值是否为0,如果是0,则自动删除指针对象。
示例代码如下:
下面是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;
};
同样的先上一张图。
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;
};
相关文章推荐
- 智能指针与句柄类(三)
- 智能指针的实现及原理 + Good ! 句柄类
- 智能指针与句柄类(一)
- 智能指针是一种类,别名称为句柄类
- 智能指针CComPtr 和 CComQIPtr(转)
- boost 智能指针auto_ptr scoped_ptr shared_ptr scoped_array shared_array 总结
- 【C/C++】智能指针auto_ptr,share_ptr,unique_ptr
- C++14 智能指针unique_ptr、shared_ptr、weak_ptr
- C++中智能指针的设计和使用 .
- boost 智能指针 --- 关于性能的少数派报告
- 智能指针学习
- C++ 智能指针 shared_ptr unique_ptr weak_ptr
- C++弱引用智能指针weak_ptr的用处
- C++智能指针
- OSG中的智能指针
- 智能指针
- 智能指针
- 以对象管理资源——C++智能指针auto_ptr简介
- Effective C++——》条款17:以独立语句将newed的对象置入智能指针
- STL--智能指针(auto_ptr)