Cocos2d-x中所有内存管理方式的基础是引用计数,动态分配一个Ref对象后其引用计数为1,并通过retain和release来增持和减少其引用计数。引用计数本身并不能帮助我们进行内存管理。
为了正确地释放对象的内存,Cocos2d-x使用Objective-C里面的自动回收池的机制来管理对象内存的释放。Autorelease有点类似于一个共享的”智能指针”,该”智能指针”的作用域为一帧,该帧结束后,它将释放自己的引用计数,此时,如果该对象没有被其他”共享指针”引用,则对象被释放。如果对象被引用,则保留。
Vector和Map<K,V>通常用来和autorelease一起工作,我们通常应该将一个autorelease对象加入到Vector或者Map中,例如Node将所有的子元素存储在一个Vector<Node*>中。Vector和Map对新加入的元素执行retain操作,并对从中移除的元素执行release操作,这样元素在从Vector或者Map中移除的时候就会被自动释放。
对于单个的非集合元素对象,我们往往不会通过autorelease来进行管理,除非它是一个临时对象。这个时候我们只能手动使用retain和release来进行管理,这其实等价于通过new和delete来进行内存管理,这样的情况就容易导致内存管理问题。
因此,Cocos2d-x 在3.1中引入了智能指针RefPtr,RefPtr是基于RAII[引用6]实现的,RAII的全称为Resource Acquisition Is Initialization,是由C++之父Bjarne Stroustrup提出的管理动态内存的方法。在RAII中,动态资源的持有发生在一个对象的生命周期之内,即是说在对象的构造函数中分配内存,在对象的析构函数中释放内存。这就是我们前面讲述的将动态分配的内存映射到一个自动变量上,通过自动变量的构造函数和析构函数来分配和释放内存。这可以保证资源始终会被释放,即使出现异常,也能被正常释放。这也是各种智能指针如std::shared_ptr实现的基本原理。
RefPtr实际上是模仿C++11中的std::shared_ptr实现的,它保持着一个Ref*对象的强引用,并使用Cocos2d-x自身的引用计数来管理多个智能指针对内存的共享。与shared_ptr相比,它更轻量级,并且能够结合Cocos2d-x的内存管理模型,但是它不保证线程安全,因此比shared_ptr更高效。但是,Cocos2d-x并没有提供与std::unique_ptr和std::weak_ptr类似功能的智能指针。
3.2.6.1 构造函数
RefPtr需要依赖于Ref的引用计数来管理内存,所有类型T必须是一个Ref类型,Cocos2d-x通过静态转换static_const来在编译时进行类型检查。
RefPtr提供了几个重载的构造函数,由于RefPtr变量和Ref指针是一种强引用关系,所以这些构造函数会对任何不为nullptr的Ref指针增持其引用计数,除非它是一个右值。例如:
// 转换函数
RefPtr<__String> ref2(cocos2d::String::create(“Hello”));
CC_ASSERT(strcmp(“Hello”, ref2->
为了正确地释放对象的内存,Cocos2d-x使用Objective-C里面的自动回收池的机制来管理对象内存的释放。Autorelease有点类似于一个共享的”智能指针”,该”智能指针”的作用域为一帧,该帧结束后,它将释放自己的引用计数,此时,如果该对象没有被其他”共享指针”引用,则对象被释放。如果对象被引用,则保留。
Vector和Map<K,V>通常用来和autorelease一起工作,我们通常应该将一个autorelease对象加入到Vector或者Map中,例如Node将所有的子元素存储在一个Vector<Node*>中。Vector和Map对新加入的元素执行retain操作,并对从中移除的元素执行release操作,这样元素在从Vector或者Map中移除的时候就会被自动释放。
对于单个的非集合元素对象,我们往往不会通过autorelease来进行管理,除非它是一个临时对象。这个时候我们只能手动使用retain和release来进行管理,这其实等价于通过new和delete来进行内存管理,这样的情况就容易导致内存管理问题。
因此,Cocos2d-x 在3.1中引入了智能指针RefPtr,RefPtr是基于RAII[引用6]实现的,RAII的全称为Resource Acquisition Is Initialization,是由C++之父Bjarne Stroustrup提出的管理动态内存的方法。在RAII中,动态资源的持有发生在一个对象的生命周期之内,即是说在对象的构造函数中分配内存,在对象的析构函数中释放内存。这就是我们前面讲述的将动态分配的内存映射到一个自动变量上,通过自动变量的构造函数和析构函数来分配和释放内存。这可以保证资源始终会被释放,即使出现异常,也能被正常释放。这也是各种智能指针如std::shared_ptr实现的基本原理。
RefPtr实际上是模仿C++11中的std::shared_ptr实现的,它保持着一个Ref*对象的强引用,并使用Cocos2d-x自身的引用计数来管理多个智能指针对内存的共享。与shared_ptr相比,它更轻量级,并且能够结合Cocos2d-x的内存管理模型,但是它不保证线程安全,因此比shared_ptr更高效。但是,Cocos2d-x并没有提供与std::unique_ptr和std::weak_ptr类似功能的智能指针。
3.2.6.1 构造函数
RefPtr需要依赖于Ref的引用计数来管理内存,所有类型T必须是一个Ref类型,Cocos2d-x通过静态转换static_const来在编译时进行类型检查。
RefPtr提供了几个重载的构造函数,由于RefPtr变量和Ref指针是一种强引用关系,所以这些构造函数会对任何不为nullptr的Ref指针增持其引用计数,除非它是一个右值。例如:
// 转换函数
RefPtr<__String> ref2(cocos2d::String::create(“Hello”));
CC_ASSERT(strcmp(“Hello”, ref2->