memnew 宏

memnew 是一个宏,用于自定义对象的内存分配和初始化。其写法如下:

#define memnew(m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", "") m_class))

解释如下:

  1. new ("", "") m_class:调用了自定义的 operator new,传递了两个字符串参数(实际用作避免与引擎的 operator new 冲突),用于分配内存。
  2. ::godot::_pre_initialize<...>():在分配前做一些类型相关的初始化(模板元编程,通常为空实现)。
  3. ::godot::_post_initialize(...):在对象构造后做一些后处理(比如注册、钩子等),并返回对象指针。
  4. 逗号表达式保证先执行 _pre_initialize,再执行 _post_initialize 并返回其结果。

这样做的目的是:

  • 统一对象的分配和初始化流程,便于内存管理和调试。
  • 支持 Godot 的自定义内存分配策略。

memdelete 宏

Ref

Ref 是一个模板类,用于管理 Godot 引擎中继承自 RefCounted 的对象的引用计数。它的主要作用是自动管理对象的生命周期,防止内存泄漏和悬挂指针。

核心要点如下:

  • Ref<T> 持有一个指向类型为 T(通常继承自 RefCounted)的指针 reference
  • 通过引用计数机制,Ref 会在对象无人引用时自动释放内存。
  • 支持拷贝、赋值、比较、指针操作(如 ->*),用法类似智能指针。
  • 提供 is_valid()is_null() 方法判断引用是否有效。
  • 构造、赋值和析构时会自动增加或减少引用计数。
  • 适用于 Godot C++ 扩展开发中资源和对象的安全管理。

简而言之,Ref 是 Godot C++ 绑定中的智能引用计数指针,专为 Godot 对象安全管理而设计。

为什么不直接使用智能指针(如 std::shared_ptr)?

Ref 没有直接用 std::shared_ptr 主要原因如下:

  1. Godot 的对象系统需要自定义的引用计数逻辑(如 reference()/unreference()),以便与引擎的生命周期和信号机制集成。
  2. Godot 对象有特殊的类型转换、绑定和垃圾回收需求,Ref 支持 Godot 的类型安全和对象查找。
  3. std::shared_ptr 不支持 Godot 的 Variant、信号、资源系统等特性。
  4. Godot 需要跨语言(如 GDExtension、脚本)一致的对象管理,Ref 设计为与 Godot 内部一致。

简言之,Ref 是为 Godot 引擎量身定制的智能指针,满足其特殊需求,而 std::shared_ptr 无法直接满足这些需求。