智能指针在C++11的标准中已经存在了,分别是unique_ptr,shared_ptr,weak_ptr,其中最常用的应该是share_ptr,它采用引用计数的方式管理内存,当引用计数为0的时候,自动释放内存,但是由于shared_ptr考虑到了线程安全,所以会存在有较大的性能损失。所以在实时游戏开发中,往往不会用到shared_ptr。
在cocos2d-x3.2以及更高的版本中,cocos2d-x提供了自己的智能指针方案——RefPtr,这套方案实际上也是模仿C++11中的shared_ptr机制实现的,他结合了Cocos2d-x自身的引用计数来管理内存,当然为了性能,他牺牲了线程安全(cocos2d-x的引用计数不支持线程安全)。
下面看看cocos2d-x中智能指针的源码,首先是构造函数
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); }
#define CC_REF_PTR_SAFE_RETAIN(ptr) do { if (ptr) { const_cast<Ref*>(static_cast<const Ref*>(ptr))->retain(); } } while (0);核心就是retain,保持一个强引用。
下面是声明智能指针的用法
//inline RefPtr() RefPtr<int> a; //inline RefPtr(T * ptr) RefPtr<int> b(new int); //inline RefPtr(const RefPtr<T> & other) RefPtr<int>c(b); //inline RefPtr(RefPtr<T> && other) RefPtr<int>d(std::move(b)); //inline RefPtr(std::nullptr_t ptr) RefPtr<int>d(nullptr);
inline ~RefPtr() { CC_REF_PTR_SAFE_RELEASE_NULL(_ptr); }
#define CC_REF_PTR_SAFE_RELEASE_NULL(ptr) do { if (ptr) { const_cast<Ref*>(static_cast<const Ref*>(ptr))->release(); ptr = nullptr; } } while (0);实际上就是对其release并且置空。
另外,也提供了移动赋值函数以及赋值函数。
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; }
RefPtr<int> b(new int); b = nullptr;
RefPtr还重载了指针操作符 *和-> 方便直接调用内部指针,所以其使用方法与普通指针一样。也提供了get方法获取到指针
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 void weakAssign(const RefPtr<T> & other) { CC_REF_PTR_SAFE_RELEASE(_ptr); _ptr = other._ptr; }
void a() { RefPtr<Texture2D> l; l.weakAssign(new Texture2D); // -- doSomething return; }
auto aa = new Texture2D; aa->autorelease();但是这一种方法的释放时机是在一帧的结束,而智能指针的释放时机是函数的结束,所以相较于下一种方法,智能指针会效率更高
【深入了解cocos2d-x 3.x】内置数据结构(1)——智能指针
原文:http://blog.csdn.net/nxshow/article/details/44699409