Files
XCEngine/docs/api/XCEngine/Core/RefCounted/RefCounted.md

3.1 KiB

RefCounted

命名空间: XCEngine::Core

类型: class

头文件: XCEngine/Core/RefCounted.h

描述: 一个侵入式原子引用计数基类,通过 AddRef() / Release() 管理对象生命周期。

角色概述

RefCounted 代表的是经典 intrusive reference counting 模式:

  • 引用计数字段存放在对象内部
  • 调用者手工执行 AddRef() / Release()
  • 计数归零时对象自己 delete this

这和 SmartPtr 里的 Ref<T> = std::shared_ptr<T> 是两套完全不同的所有权模型。当前代码里没有自动桥接它们,这一点非常重要。

当前实现行为

1. 初始引用计数是 1

构造函数会把 m_refCount 初始化为 1tests/core/test_core.cpp 已验证这一点。

这意味着默认语义是:

  • new DerivedFromRefCounted() 返回的对象立刻拥有一个初始引用
  • 你不需要在创建后先手工 AddRef()

2. Release() 在归零时直接 delete this

当前实现是:

if (--m_refCount == 0) {
    delete this;
}

因此:

  • 一旦 Release() 让计数归零,对象就立即自删除
  • 之后原来的裸指针立刻失效

这是 intrusive RC 最典型也最危险的一点。文档必须把它明确写出来。

3. 计数字段是原子变量

m_refCount 类型是 std::atomic<uint32_t>,所以单次增减操作具备基础原子性。

但这不等于“整个对象生命周期管理完全线程安全”。对象自己的其他状态并没有额外同步保护。

与 SmartPtr 的关系

当前项目里同时存在:

  • RefCounted
  • Ref<T> / UniqueRef<T> / MakeRef() / MakeUnique()

这很容易让人误以为 RefCounted 会自动和 Ref<T> 协同工作,但当前事实是:

  • Ref<T> 只是 std::shared_ptr<T>
  • RefCounted 只是手工 intrusive RC 基类
  • 两者当前没有自定义 deleter、适配器或统一 ownership 框架

所以使用时必须明确选一套模型,而不是混用后想当然。

使用边界

  • 这种类型只适合堆分配对象。
  • 不应把栈对象或外部所有权对象拿来调用 Release()
  • 如果对象已经由别的 RAII 所有权工具接管,再手工 Release() 可能导致双重销毁。

测试覆盖

tests/core/test_core.cpp 已覆盖:

  • 初始引用计数
  • AddRef()
  • 多次链式加减引用
  • Release() 归零后自销毁路径

线程语义

  • 引用计数增减是原子的。
  • 对象其他成员状态没有自动同步。
  • 释放最后一个引用的线程会执行 delete this

当前实现限制

  • 没有 weak reference 机制。
  • 没有和 std::shared_ptr / Ref<T> 的自动互操作。
  • 只适合明确采用 intrusive RC 的对象模型。

相关方法

相关指南

相关文档