打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Winx基本类使用指南之C++标准扩展(AutoFreeAlloc)
分类: winx 2006-11-30 14:06 3394人阅读 评论(2) 收藏 举报
 

 

Winx基本类使用指南之C++标准扩展(AutoFreeAlloc[1]

 

C++中,一般有两种内存分配的方式:

1.     传统的配对方式

         C++中的newdelete

         Callocfree

         Windows APIGlobalAllocGlobalFreeHeapAllocHeapFree

这种分配方式首先一件事就是要记住在分配内存后一定要释放,这一点在吃过几次亏后总是能够记住;但是在某个程序段的分支或异常处理多起来时(并且这个程序段不止一次的分配内存),再使用这种内存分配方式就会头大如斗(我想,绝大多数的C++程序员都应该对此有所体会)。

 

2.     使用智能指针

使用智能指针可以解决传统的配对方式的问题,但同时却又引出了新的问题。智能指针品种很多,记住它们的各种规则更是困难。本人愚苯,每次使用boost库中的智能指针,总是先要去看它们的帮助文档。

 

现在终于有了第三种内存分配方式,这就是WinxAutoFreeAlloc机能(这个机能属于Winx的标准C++的扩展部分),其基本原理是由一个AutoFreeAlloc负责某程序段中所有的内存分配,而不管所分配内存是由什么对象使用,在该程序段结束时,再由这个AutoFreeAlloc释放所有被分配的内存。对于具体的底层实现机制,感兴趣的朋友可以参照xushiwei最袖珍的垃圾回收器

 

下面就转入正题,介绍一下AutoFreeAlloc的使用方法及在使用中要注意的一些问题。

 

使用AutoFreeAlloc的例子

下面的例子主要演示了使用AutoFreeAlloc的一些方式(在main函数中),其主要功能是首先定义一个分配器,然后为一系列对象分配内存。

class ClassA

{

private:

      int            var_int_;

      double           var_double_;

public:

      ClassA() { }

};

 

class ClassB

{

private:

      int            var_int_;

      double           var_double_;

public:

      ClassB() : var_int_(0), var_double_(0.0)  { }

      ClassB(const ClassB& cb) :

            var_int_(cb.var_int_), var_double_(cb.var_double_)

      {}

     

      ~ClassB() { }

};

 

 

class ClassC

{

private:

      int            var_int_;

      double           var_double_;

      ClassB           class_b_;

public:

 

      ClassC() { }

      ~ClassC() { }

};

 

int main()

{

      AutoFreeAlloc alloc;

 

      ClassA* ca = STD_NEW(alloc, ClassA);

      ClassA* caArray = STD_NEW_ARRAY(alloc, ClassA, 100);

        for (int i = 0; i < 100; ++i)

        {

                // print address of each element of Array caArray

                cout << caArray + i << endl;

      }

 

      ClassB cbTemp;

      // assign cbTemp to cb

      ClassB* cb = STD_NEW(alloc, ClassB)(cbTemp);

      ClassB* cbArray = STD_NEW_ARRAY(alloc, ClassB, 100);

 

      ClassC* cc = STD_NEW(alloc, ClassC);

      ClassC* ccArray = STD_NEW_ARRAY(alloc, ClassC, 100);

 

      // assign 1 to i1

      int* i1 = STD_NEW(alloc, int)(1);

      int* i2 = STD_NEW_ARRAY(alloc, int, 100);

 

      // assign 0.0 to d1

      double* d1 = STD_NEW(alloc, double)(0.0);

      double* d2 = STD_NEW_ARRAY(alloc, double, 100);

 

        int* i3 = STD_ALLOC(alloc, int);

        int* i4 = STD_ALLOC_ARRAY(alloc, int, 100);

 

        double* d3 = STD_ALLOC(alloc, double);

      double* d4 = STD_ALLOC_ARRAY(alloc, double, 100);

     

        char* s1 = STD_NEW(alloc, char);

        *s1 = 'T';

        cout << *s1 << endl;

        char* s2 = STD_NEW_ARRAY(alloc, char, 128);

        strcpy(s2, "hello world!");

        cout << s2 << endl;

 

        char* s3 = STD_NEW(alloc, char);

        char* s4 = STD_NEW_ARRAY(alloc, char, 128);

        strcpy(s4, "hello world 2!");

      cout << s4 << endl;

      return 0;

}

 

通过上面的例子可以看出,AutoFreeAlloc的使用非常简单,只有2个步骤:

1.     定义AutoFreeAlloc

2.     通过STD_NEWSTD_NEW_ARRAYSTD_ALLOCSTD_ALLOC_ARRAY4个宏中的一个来分配内存(或者说创建对象),这是不是有点象java中的new操作呢?J

 

内存分配器的定义

内存分配器的定义是用main函数中的第一条语句来完成的:

AutoFreeAlloc alloc;

这条语句很简单,但一些幕后的细节我们需要了解。我们再来看AutoFreeAlloc是有一个typedef来定义的:

typedef AutoFreeAllocT<StdLibAlloc> AutoFreeAlloc;

StdLibAlloc的定义如下:

 

struct StdLibAlloc

{

      static void* allocate(size_t cb)                                   

      { return malloc(cb); }

      static void* allocate(size_t cb, DestructorType fn)     

      { return malloc(cb); }

      static void* allocate(size_t cb, int fnZero)                 

      { return malloc(cb); }

 

      static void deallocate(void* p)                  { free(p); }

      static void deallocate(void* p, size_t)      { free(p); }

      static void swap(StdLibAlloc& o)                  {}

 

};

 

从这里可以看出,我们使用AutoFreeAllocT来管理分配的内存,StdLibAlloc进行实际的内存分配(只是简单的使用allocfree函数对)。这样就提供了一种机制,我们可以自己定义实际的内存分配方式。

现实世界中,充满了各种各样的内存分配方式。比如说我们需要创建映射文件(CreateFileMapping)来作为内存使用,或者说我们要使用共享内存,都可以建立自己的分配器,然后统一用AutoFreeAllocT进行管理(只要建立的分配器符合要求类似于StdLibAlloc实现6个函数)。

一般情况下,只要直接使用AutoFreeAlloc就可以了。但为了适应特别需要,这里简单介绍了一下StdLibAlloc

 

为对象分配内存

为对象分配内存时非常简单,只要使用以下任意一个宏即可:

STD_NEW(alloc, Type)

STD_ALLOC(alloc, Type)

其中的alloc指定分配器,Type指定对象类型。STD_NEWSTD_ALLOC之间的区别下文说明。

 

为数组分配内存

为数组分配内存时,可以使用以下宏:

STD_NEW_ARRAY(alloc, Type, count)

STD_ALLOC_ARRAY(alloc, Type, count)

其中的alloc指定分配器,Type指定对象类型,count指定数组的大小。STD_NEW_ARRAYSTD_ALLOC_ARRAY之间的区别下文说明。

 

STD_NEWSTD_NEW_ARRAY)与STD_ALLOCSTD_ALLOC_ARRAY)的区别

 

STD_NEW宏先分配内存,然后使用placement new操作符来构造对象,释放内存时先调用被构造对象的析构函数,然后再释放内存(针对C++中的原生类型(int,char,long,double等),会使用模板特化技术,消除对原生类型的析构调用)。

STD_ALLOC宏只是分配内存,释放内存时直接释放。

STD_NEW_ARRAYSTD_ALLOC_ARRAY之间的区别与此类似。

 

释放所分配的内存

AutoFreeAlloc会自动释放内存,你也可以通过调用AutoFreeAllo的成员函数clear()手工释放内存(通常不需要)。

 

一点补充:释放内存时如何调用对象的析构函数

虽然是否知道AutoFreeAlloc释放内存时如何调用对象的析构函数对我们使用AutoFreeAlloc没有影响,但理解这一点,在我们使用AutoFreeAlloc时更能够做到心中有数。

 

我们知道(参照xushiwei最袖珍的垃圾回收器),在AutoFreeAllocallocate函数中指定了对象的清除函数(这里使用清除是为了与析构区别开来),请见如下代码:

template <class _Alloc, int _MemBlockSize = MEMORY_BLOCK_SIZE>

class AutoFreeAllocT

{

    void* winx_call allocate(size_t cb, DestructorType fn);

};

 

其中的DestructorType参数指定了对象的清除函数。其定义如下:

typedef void __FnDestructor(void* data);

typedef __FnDestructor* DestructorType;

 

我们再来看STD_NEW的宏定义:

#define STD_NEW(alloc, Type)                                    /

        ::new((alloc).allocate(sizeof(Type),             /

std::DestructorTraits<Type>::destruct)) Type

 

DestructorTraits的定义如下:

template <class Type>

struct DestructorTraits

{

    static void winx_call destruct(void* data)

    {

        ((Type*)data)->~Type();

    }

};

 

通过这些代码片段,我们就可以知道AutoFreeAlloc释放内存时会调用DestructorTraits<Type>::destruct函数,而在DestructorTraits<Type>::destruct函数中会调用对象的析构函数。

对于数组,其做法与此类似,这里就不详细讲了。



[1] 本文中部分代码引自winx库中的源代码,但为便于理解考虑,有些细节代码被删除

更多0
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
python – 通过pybind11返回numpy数组
《c++ primer》 第12章 动态内存 学习笔记
浅谈C++普通指针和智能指针管理动态内存的陷阱
TBB: concurrent_queue 高性能的奥秘 – 英特尔? 软件网络博客 - 中文
JSON用法简介
4.8 数组+结构+指针
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服