垃圾回收
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 来实现自动释放内存的。
