垃圾回收
C++ 中使用 new
运算符创建的对象需要使用 delete
释放,否则会造成内存泄漏。引擎中使用了大量的指针,如果不妥善处理它们,程序占用的内存将成倍的增长。
自动回收垃圾的过程
Easy2D 提供了 gcnew
来代替 new
,使用 gcnew
创建的对象将被 垃圾回收器(GC)
跟踪,当这个对象不再被需要时,GC 会自动 delete 它。
gcnew 仅能创建继承自 easy2d::Object 的对象。
GC
判断一个对象是否需要被释放的方法如下:
- Object 基类对象保存了一个引用计数,这个计数表示它被 “使用” 的次数,初始的引用计数为 1
- 当引用计数
<= 0
时,对象被 delete,相对的,当引用计数> 0
时,对象被保留 - 使用 gcnew 创建的对象,下一帧会自动将引用计数减 1,所以未被使用的对象会被清理
比如我们使用 gcnew
创建了一个 Scene
,下面的代码展示了引用计数的变化
// 创建一个场景,此时引用计数为 1
auto scene = gcnew Scene;
// 下一帧 scene 的引用计数自动减 1
// 如果不对这个 scene 做任何操作,那么下一帧 scene 会被删除
如果我们正常使用这个 scene 对象,它的引用计数会这样变化:
// 创建一个场景,此时引用计数为 1
auto scene = gcnew Scene;
// 进入场景,它的引用计数变为 2
SceneManager::enter(scene);
// 下一帧 scene 的引用计数自动减 1,引用计数变为 1,所以不会被清理
// 退出场景,它的引用计数变为 0,scene 会被自动删除
SceneManager::back();
如何控制引用计数
Object 的 retain
和 release
方法可以使引用计数加一或减一,这两个方法应成对使用。
auto node = gcnew Node;
// 手动增加引用计数,这个节点即使脱离场景也可以存活
node->retain();
// 手动减少引用计数,释放对这个节点的引用
node->release();
Object 的 autorelease
方法会把对象放入回收池中,回收池中的对象会在下一帧被清理。
gcnew
也是通过调用 autorelease
来实现自动释放内存的。