cocos2d智能指针 转自:http://blog.csdn.net/nxshow/article/details/44699409
智能指针在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);
}
RefPtr提供了多个构造函数,
可以用默认构造函数声明一个空智能指针,
用别的指针来声明一个智能指针,
也提供了移动构造函数将内存偷过来,
复制构造函数保持内存的强引用。
构造函数最为重要的莫过于CC_REF_PTR_SAFE_RETAIN宏了,
它是智能指针专用的宏,
在外部是引用不到的。
实现如下
#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); }
还重载了一系列的操作符,这里就不做分析了,最后还有一个比较关键的函数,weakAssign,它对保持对一个指针的弱引用,实现如下:
inline void weakAssign(const RefPtr<T> & other)
{
CC_REF_PTR_SAFE_RELEASE(_ptr);
_ptr = other._ptr;
}
相对于其他的复制函数,他少了retain操作,
说明它并不保持对other的强引用,
但是析构的时候我们发现,
依旧会release一次,那么这个函数会有什么奇妙的作用呢。
看下面的函数片段
void a()
{
RefPtr<Texture2D> l;
l.weakAssign(new Texture2D);
// -- doSomething
return;
}
函数中并没有delete,但是依旧不会造成内存泄露,当然,还有一种方法也不会造成内存泄露,也就是
auto aa = new Texture2D;
aa->autorelease();
但是这一种方法的释放时机是在一帧的结束,
而智能指针的释放时机是函数的结束,
所以相较于下一种方法,智能指针会效率更高
cocos2d智能指针 转自:http://blog.csdn.net/nxshow/article/details/44699409的更多相关文章
- 转:Java面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101
Java面试题集(51-70) Java程序员面试题集(51-70) http://blog.csdn.net/jackfrued/article/details/17403101 摘要:这一部分主要 ...
- http://blog.csdn.net/LANGXINLEN/article/details/50421988
GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地 ...
- https://blog.csdn.net/u011489043/article/details/68488459
转自https://blog.csdn.net/u011489043/article/details/68488459 String 字符串常量 StringBuffer 字符串变量(线程安全) ...
- 数组中&a与&a[0]的区别 转载自http://blog.csdn.net/FX677588/article/details/74857473
在探讨这个问题之前,我们首先来看一道笔试题,如下: [摘自牛客网]下列代码的结果是:(正确答案是 C) main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)( ...
- Win32消息循环机制等【转载】http://blog.csdn.net/u013777351/article/details/49522219
Dos的过程驱动与Windows的事件驱动 在讲本程序的消息循环之前,我想先谈一下Dos与Windows驱动机制的区别: DOS程序主要使用顺序的,过程驱动的程序设计方法.顺序的,过程驱动的程序有一个 ...
- IntelliJ Idea 常用快捷键列表 (需整理下) https://blog.csdn.net/dc_726/article/details/42784275
[常规] https://blog.csdn.net/dc_726/article/details/42784275https://jingyan.baidu.com/article/59a015e3 ...
- http://blog.csdn.net/v_july_v/article/details/6543438
本文转载至: http://blog.csdn.net/v_july_v/article/details/6543438 算法 程序员面试.算法研究.编程艺术.红黑树.数据挖掘5大经典原创系列集锦与总 ...
- 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)
原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解 By 岩之痕 目录: 一:综述 ...
- http://blog.csdn.net/java2000_wl/article/details/8627874
http://blog.csdn.net/java2000_wl/article/details/8627874
随机推荐
- dos命令复制当天生成的以日期为文件名的文件
1.利用SqlServer的自动备份功能,将数据自动备份,备份出的文件格式如下: db_backup_201001270930.bak 2.编辑bat脚本 ...
- 10月21上午PHP基础
新建的php文件必须要放在wamp安装目录下的www文件夹里.如果拿到别的地方,php无法运行,将显示错误. <?php?> //嵌入php的方式 <?php //嵌入php方式的开 ...
- rem自适应布局的回顾总结
使用rem实现自适应布局,应该算是当前移动前端的一大趋势,有些人对此还有点迷惑,搞不懂rem是如何实现自适应布局,如何根据设计稿来调整rem的值?rem布局如何用雪碧背景图片?rem一定要加载JS吗? ...
- %1 不是有效的Win32应用程序
用 64bit 的 Python 调用 32bit 的 Dll 会出错
- Nancy总结(二)记一次Nancy 框架中遇到的坑
记一次Nancy 框架中遇到的坑 前几天,公司一个项目运行很久的Nancy框架的网站,遇到了一个很诡异的问题.Session 对象跳转到另外一个页面的时候,session对象被清空了,导致用户登录不上 ...
- osharp3 整合 dbcontextscope 文章2 将dbcontext的创建收回到ioc管理
osharp3 整合 dbcontextscope 后,,dbcontextscope 对dbcontext管理的很好,做到,用到时创建,不用时销毁,下面看一个 trace aspx.page: En ...
- phpcms使用细节
1.在模板中使用php语句 <?php for ($i=0; $i < 10; $i++) { echo $i."#######<br>"; }?& ...
- android-解决EditText的inputType为Password时, 字体不一致的问题
今天做项目的时候,发现当edittext 的InputType为password时,它的字体和原来不一样: 网上找了一下,给出了解决办法: 第一: 去掉xml文件中的password配置,在代码中编写 ...
- linux下vim更改注释颜色
我linux下默认底色是黑色,字体是绿色,但是注释默认是蓝色,,很不爽...所以要更改注释颜色......以下文章来自转载. from: http://blog.csdn.net/gz109/arti ...
- jQuery.extend和jQuery.fn.extend的区别?
jquery 本身 是由 Resig: 莱希格, 一个美国的小伙子小伙伴开发的, 在2005年 prototype发表之后, 在2006年1月发表的, 后来进入mozilla工作, mozilla的j ...