C++ Memory System Part3 : 优化

前面的系列咱们讲了自定义new和delete操做,其中针对deleteArray的问题还有须要优化的地方。咱们此次就针对POD类型进行一次优化。html

下面的代码是针对POD类型的模板函数实现,分别为NewArrayPOD和DeleteArrayPOD:wordpress

template <typename T, class ARENA>
T* NewArrayPOD(ARENA& arena, size_t N, const char* file, int line)
{
  return static_cast(arena.Allocate(sizeof(T)*N, file, line));
}

template <typename T, class ARENA>
void DeleteArrayPOD(T* ptr, ARENA& arena)
{
  arena.Free(ptr);
}

 

从上面能够看出,针对POD类型,咱们不须要调用析构函数,只须要将内存释放便可,因此其区别于非POD类型。可是若是实现了POD和非POD两个版本的函数,该如何让咱们的宏根据类型本身调用合适的函数呢?函数

咱们采用的方式是放弃NewArrayPOD和DeleteArrayPOD这种另外实现一个函数的方式,而是重载NewArray和DeleteArray函数,使宏根据参数来正确调用对应的函数。咱们首先要实现的是一个traits-class,它用来判断一个类型是否是POD类型。这能够经过定义一个基础模板类和一些特化版原本实现,代码以下:优化

 

template <typename T>
struct IsPOD
{
  static const bool Value = false;
};

template <>
struct IsPOD<char>
{
  static const bool Value = true;
};

template <>
struct IsPOD<int>
{
  static const bool Value = true;
};

// etc.

对于任何一个给定的类型T,咱们能够经过编译期常量IsPOD<T>::value来肯定T是否为一个POD类型。固然了,若是使用了C++11及之后的标准,标准库中就实现了std::is_pod。ui

 

两个重载版本的函数实现以下:spa

template <typename T, class ARENA>
T* NewArray(ARENA& arena, size_t N, const char* file, int line, NonPODType)
{
  // implementation for non-POD types
}

template <typename T, class ARENA>
T* NewArray(ARENA& arena, size_t N, const char* file, int line, PODType)
{
  // implementation for POD types
}

template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena, NonPODType)
{
  // implementation for non-POD types
}

template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena, PODType)
{
  // implementation for POD types
}

 

固然了,看到上面的代码后,你可能会问,C++的重载是根据类型来的,又不是根据值,咱们不能只经过一个true和一个false来重载函数。因此为了让上面的代码可以正确工做,咱们须要再实现一个模板黑魔法称为type-based dispatching。code

template <bool I>
struct IntToType
{
};

typedef IntToType<false> NonPODType;
typedef IntToType<true> PODType;

 

这样,咱们就能够将上一节中的宏定义修改成:htm

// old version
#define ME_NEW_ARRAY(type, arena) NewArray<TypeAndCount<type>::Type>(arena, TypeAndCount<type>::Count, __FILE__, __LINE__)

// new version
#define ME_NEW_ARRAY(type, arena) NewArray<TypeAndCount<type>::Type>(arena, TypeAndCount<type>::Count, __FILE__, __LINE__, IntToType<IsPOD<TypeAndCount<type>::Type>::Value>())

 

有点小长,可是若是理解了背后的技巧和原理,实现起来其实并不复杂。可是咱们还有最后一个问题,就是在宏定义#define OM_DELETE_ARRAY(object, arena) DeleteArray(object, arena)中不能直接使用Is_POD<T>方法,由于obejct自己是一个值,不是一个一个类型,咱们又不想显式的再用一个参数来制定类型,由于编译器已经知道了类型,因此咱们要作的就是让编译器本身推到出类型再调用DeleteArray函数,因此咱们只需将DeleteArray函数封装在一个模板函数中,就能够实现这一点,代码以下:blog

 

template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena)
{
  DeleteArray(ptr, arena, IntToType<IsPOD<T>::Value>());
}

 

至此为止,咱们对POD和非POD类型的优化工做已经结束,如今咱们能够高效的使用自定义的OM_NEW_ARRAY和OM_DELETE_ARRAY了。内存

 

 

 

 

 

参考link:

 

https://stoyannk.wordpress.com/2018/01/10/generic-memory-allocator-for-c-part-3/

 

https://bitsquid.blogspot.com/2010/09/custom-memory-allocation-in-c.html

 

https://blog.molecular-matters.com/

相关文章
相关标签/搜索