内存管理之后就是对象管理了,在c++中,为了管理对象的生命周期,需要设计智能指针来管理相应对象的创建和删除,比如std的智能指针。现在也比较推荐直接使用std的智能指针,但在2007年c++11的功能还在好像TR命名空间下,并不是正式版本,所以我们设计了自己的智能指针系统,并且嵌入了下篇文章需要提到的反射信息。不过需要清楚一点,智能指针在管理对象时虽然会带来很多方便,但是它自身也会有各种问题,比如大量使用会有一定的性能损失,比如毕竟不是完全的GC会出现循环引用问题,虽然可以用WeakPtr去规避,但是毕竟需要在写代码的时候多加小心。总的来说利大于弊吧。
首先需要定义一个PtrData,提供智能指针相关接口,
template
void AddRef() // 增加引用计数
void Release() // 减少引用计数,如果为0,删除Data,同时调用ReleaseWeak
void AddRefWeak() // 增加弱引用计数
void ReleaseWeak() // 减少弱引用计数,如果为0,删除this
// 下面的两个接口时为了反射用的
Identifier & GetTypeName() // 数据类型的名称,包含反射相关信息,通过模板推导类型,调用系统RTTI接口typeid获得type_info,不同类型进行cache
void * QueryInterface(const Identifier & typeName) // 通过类型名请求相应接口,如果是本身的类型直接返回,如果不是获取反射的TypeInfo,再通过TypeInfo获取相应数据
其次定义几种智能指针类型,其中包含数据Data和PtrData两部分,尽量在栈上创建,不要使用new创建,
NullPtr // 空指针
BasePtr // 基本指针,所有指针的基类
SharedPtr : BasePtr // 创建增加PtrData引用计数、释放删除PtrData引用计数
WeakPtr : BasePtr // 创建增加PtrData弱引用计数、释放删除PtrData弱引用计数,实际使用时转为SharedPtr
AutoPtr : BasePtr // 类似于SharedPtr,但是智能有一个所有者,新的赋值和构造都会删除自身的PtrData的所有权
TempPtr : BasePtr // 不增加任何PtrData引用计数,一般用于参数传递,不需要保证数据的有效性时,实际使用时转为SharedPtr
上面就是智能指针的内容了,同样现在可以使用std智能指针作为替代,不过里面使用unique_ptr代替了auto_ptr,同时禁止了复制构造和赋值,如果一定要使用需要用std::move标识。
除了智能指针,同时还定义了Object,作为所有需要管理的对象的基类
TempPtr(void) Owner // 用来保存指向对象的智能指针
衍生的会有接口
OnCreate
OnDestroy
过程中会用到一些功能模板,
/// check
template
template
template
template
template
template
/// remove
template
template
template
template
template
template
template
template
template
template
template
template
/// to variable type
template
template
template
/// to param type
template
template
template
/// to reference type
template
{
typedef T & result;
static inline result cast(T * ptr) { return *ptr; }
};
template
{
typedef T & result;
static inline result cast(T * ptr) { return *ptr; }
};
template<> struct to_reference_type
{
typedef void* & result;
static inline result cast(void * ptr) { return *(void**)ptr; }
};
/// select
template
template
/// cast to
template
{
private:
static FROM & source_object();
static int return_type(TO &);
static char return_type(…);
public:
enum
{
result = sizeof(int) == sizeof(return_type(source_object()))
};
};
/// select type name
template
{
static inline const Identifier & result()
{
static bool initialized = false;
static Identifier name;
if (!initialized)
{
Identifier rtti(TypeName(typeid(T)));
InterlockedExchange((long*)&rtti, InterlockedExchange((long*)&name, *(long*)&rtti));
initialized = true;
}
return name;
}
};
struct ChangeTypeName {};
template
template
template
template
{
typedef typename remove_all
typedef typename_fromrtti
};
template<> struct select_typename
{
typedef typename_fromrtti
};
template
{
};
#define TYPE_NAME(className) typename_of
#define ptr_new by_value << new
#define ptr_new_reference by_reference <<
template
{
static inline PtrData * by_value(T * value) { return new PtrData
static inline PtrData * by_reference(T * value) {return new PtrData
};
template
{
static inline PtrData * by_value(T * value) { return new PtrData
static inline PtrData * by_reference(T * value) {
if (value) {
IPtrData * ret = value->Owner().GetRawPtrData();
if (ret){ ret->AddRef(); return ret; } else return by_value(value); }
return NULL;
}
};
template
{
static inline IPtrData * by_value(T * value) { return value; }
static inline IPtrData * by_reference(T * value)
{ value->AddRef(); return value; }
};
interface UsePtrData {};
template
template
{
typedef typename select<
can_cast_to
ptrdata_impl
typename select<
can_cast_to
object_impl
default_impl
>::result
>
>::result
>::result result;
};
enum BY_VALUE { by_value };
enum BY_REFERENCE { by_reference };
template
template
另外在使用时会加入一些模板的特例化。
- 本文固定链接: http://www.wy182000.com/2018/09/24/游戏引擎设计系列2-对象管理/
- 转载请注明: wy182000 于 Studio 发表