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

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

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。

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

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。

template <bool I>
struct IntToType
{
}; typedef IntToType<false> NonPODType;
typedef IntToType<true> PODType;

这样,我们就可以将上一节中的宏定义修改为:

// 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函数封装在一个模板函数中,就可以实现这一点,代码如下:

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/

C++ Memory System Part3 : 优化的更多相关文章

  1. 内存泄漏 Memory Leaks 内存优化 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. gem5: 使用ruby memory system中的mesh结构 出现AssertionError错误

    问题:在使用ruby memory system中的mesh结构測试时,出现例如以下错误: Traceback (most recent call last): File "<stri ...

  3. PatentTips - Mechanisms for strong atomicity in a transactional memory system

    BACKGROUND Advances in semi-conductor processing and logic design have permitted an increase in the ...

  4. Bit error testing and training in double data rate (ddr) memory system

    DDR PHY interface bit error testing and training is provided for Double Data Rate memory systems. An ...

  5. Power management in semiconductor memory system

    A method for operating a memory module device. The method can include transferring a chip select, co ...

  6. armv8 memory system

    在armv8中,由于processor的预取,流水线, 以及多线程并行的执行方式,而且armv8-a中,使用的是一种weakly-ordered memory model, 不保证program or ...

  7. C++ Memory System Part2: 自定义new和delete

    在第一部分中,我们介绍了new / delete的具体用法和背后的实现细节,这次我们将构建我们自己的小型工具集,可以使用我们自定义的allocator类来创建任意类型的实例(或者实例数组),我们需要做 ...

  8. 雪花算法对System.currentTimeMillis()优化真的有用么?

    前面已经讲过了雪花算法,里面使用了System.currentTimeMillis()获取时间,有一种说法是认为System.currentTimeMillis()慢,是因为每次调用都会去跟系统打一次 ...

  9. C++ Memory System Part1: new和delete

    在深入探索自定义内存系统之前,我们需要了解一些基础的背景知识,这些知识点是我们接下来自定义内存系统的基础.所以第一部分,让我们来一起深入了解一下C++的new和delete家族,这其中有很多令人吃惊的 ...

随机推荐

  1. 使用java实现单链表----(java中的引用就是指针)

    //一直以为java中没有指针,其实java的引用就是指针,只不过堆栈中的引用储存了在堆中的地址,可以看做java中的指针.public class sibgleLink<E> { // ...

  2. Oracle 触发器 删除操作时再查询本表数据 功能不正确

    背影如下: 表名,WFGTEST create table WFGTEST ( NAME1 ) not null, NAME2 ), CAPACITY ,) ) 表结构如下: NAME1 NAME2 ...

  3. Window 7 Professional 多语言设置

    1. 正常情况下,WINDOW系统只提供企业和旗舰版的语言切换的界面设置,其他版本没有. 2. 首先下载语言包,然后解压待用. 3. 以管理员身份运行命令窗口,如下输入: 4. 上面完成后,下载 ht ...

  4. 201621123012 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰 ...

  5. 如何安装memcached

    软件的下载,好像从官网上只能下载未经编译的源码,需要自己编译后才能安装使用,不熟悉的用户还是直接百度搜索下载比较好,这里也提供一个下载地址给大家参考. www.newasp.net/soft/6373 ...

  6. Eclipse内存不足 增加eclipse的运行内存

    自己解决的 三.    修改Run Configurations (此方法可行) 在代码上右键,依次点击“Run As ”-> “Run Configurations ”,在Arguments  ...

  7. ThinkCMF if 标签

    用法示例: <if condition="($name eq 1) OR ($name gt 100) "> value1 <elseif condition=& ...

  8. python获取函数参数默认值的两种方法

    1.使用函数的__defaults__魔术方法 demo: # coding=utf-8 def f(a,b,c=1): pass f.__defaults__ 输出结果: (1,) 2.使用insp ...

  9. Exadata 18.1新特性--云平台存储节点升级

    1.传统方式的存储节点升级流程: (1).将存储节点升级包下载到数据库服务器,通常是DB01上. (2).解压缩存储节点升级包. (3).用升级包中的patchmgr工具滚动或非滚动地升级每个存储节点 ...

  10. python学习之路---day12

    生成器和生成器表达式一:生成器 生成器实质上就是迭代器. 三种方式获取生成器: 01:通过生成器函数 02:通过各种推导式实现生成器 03:通过数据的转换也可以获取生成器 eg:普通函数 def fu ...