日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++简单实现GC和内存池

發布時間:2024/9/30 c/c++ 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++简单实现GC和内存池 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??C++簡單實現GC和內存池

? 本章前言:

??? 這章就是為了避開傳統的new\delete創建堆對象的手法,如果使用不當指針容易出現問題,所以本章簡單的實現了引用計數垃圾回收,使用起來貌似還不錯。Bug還有待測試。

? 最終效果:

??? 通過DND_GC_CLASS宏來定義一個Student類后,用戶還是能通過正常的方法使用Student類。但宏額外生成了HStudent類,通過這個類就能方便的實現自動垃圾回收(類似C#中引用變量的效果)。

#include "DNDGC.h"

DND_GC_CLASS(Student)

public:

??? int id;

??? char data[40000];

??? Student():

??? id(0){}

??? void Init(intidi)

??? {

??????? id = idi;

??? }

??? bool operator<(constStudent& b)

??? {

??????? return id <b.id;

??? }

};

??? 首先定義一個空引用,它未指向任何值:

HStudent stu

??? 調用Initalize()實例化對象,這里實際分配內存空間:

stu.Initalize();

??? 當stu指向的堆內存沒有任何H句柄對象指向時就會被內存池標記為可用,從而給予其它對象使用。Student的成員函數通過->操作符訪問。

? 具體實現:

??? 首先實現一個簡單的動態數組模板類Vector:

??? template<typenameT>

??? class Vector

??? {

??? public:

??????? T& operator[](unsignedi)

??????? {

??????????? assert(i <m_size);

??????????? return m_vector[i];

??????? }

??????? T& At(unsignedi)

??????? {

??????????? while(i >=m_size)

??????????????? _extend();

??????????? return m_vector[i];

??????? }

??????? Vector() :

??????????? m_vector(newT[1]),

??????????? m_size(1){}

??????? Vector(unsignedsize) :

??????????? m_vector(newT[size]),

??????????? m_size(size){}

??????? ~Vector()

??????? {

??????????? delete[] m_vector;

??????? }

??????? unsigned GetSize(){return m_size;}

??? private:

??????? T* m_vector;

??????? unsigned m_size;

??????? void _extend()

??????? {

??????????? m_size<<= 1;

??????????? T* temp =new T[m_size];

??????????? memcpy_s(temp,m_size, m_vector,m_size);

??????????? delete[] m_vector;

??????????? m_vector = temp;

??????? }??

??? };

?

??? 接著實現內存池模板類,包含一個含vector節點的鏈表。當程序需要更多內存時,就會創建新的Vector節點。每個節點依次是2^(n-1)個元素。如果用戶需要一個內存,就通過查詢內存所在變量的引用計數是否為0,是就說明沒人使用,就返回此地址。

??? template<classT>

??? class PoolArray

??? {

??? private:

??????? //頁面組(一個頁面就是一個數組而已)

??????? std::list<Vector<T>*>m_pages;

??? public:

??????? //構造時初始化第一個頁,大小為1

??????? PoolArray()

??????? {

??????????? //注意類型是指針

??????????? Vector<T>*a = new Vector<T>(1);

??????????? std::cout<< "使用內存:"<< (sizeof(T)) / 1024.0f<< "KB"<< std::endl;

??????????? m_pages.push_back(a);

??????? }

??????? //要取一個位置

??????? T* GetSite()

??????? {

??????? loop:

??????????? unsigned num = 0;

??????????? for (autoiter = m_pages.begin();iter != m_pages.end(); ++iter)

??????????? {

??????????????? Vector<T>*a = *iter;

??????????????? for (unsignedi = 0; i < a->GetSize(); ++i)

??????????????? {

??????????????????? GCObject* obj = (GCObject*)&((*a)[i]);

??????????????????? if (obj->m_refNum == 0)

??????????????????? {

??????????????????????? obj->m_refNum++;

??????????????????????? return (T*)obj;

??????????????????? }

??????????????? }

??????????????? num += a->GetSize();

??????????? }

??????????? //沒有空位,則添加新頁,為以前總和的兩倍

??????????? Vector<T>*next = new Vector<T>(num<< 1);

??????????? std::cout<< "使用內存:"<< ((num << 1) * sizeof(T)) /1024.0f << "KB"? << std::endl;

??????????? m_pages.push_back(next);

??????????? goto loop;

??????? }

??????? //析構,結束程序的時候調用

??????? ~PoolArray()

??????? {

??????????? for (autoiter = m_pages.begin();iter != m_pages.end(); ++iter)

??????????? {

??????????????? Vector<T>*a = *iter;

??????????????? std::cout<< "釋放內存:"<< (a->GetSize() *sizeof(T)) / 1024.0f<< "KB"<< std::endl;

??????????????? delete a;

??????????? }

??????? }

???????

??? };

??? 其中使用內存和釋放內存的地方寫有調試語句,效果如下:

???

??? 接著寫個接口讓程序來調用,其中staticPoolArray<T> a用來存儲內存池用到的內存:

??? class Mempool

??? {

??????? //用戶禁止使用

??? private:

??????? Mempool() {};

??????? //查找T類型的auto_array

??????? template<classT>

??????? static PoolArray<T>&FindPoolArray()

??????? {

??????????? static PoolArray<T>a;

??????????? return a;

??????? }

??? public:

??????? //返回指定類型的內存池地址

??????? template<classT>

??????? static T*GetSite()

??????? {

??????????? return FindPoolArray<T>().GetSite();

??????? }

??? };

如果代碼中想要分配指定類型的一塊內存就應該調用Mempool::GetSite<TypeName>()。但規定是T得繼承于GCObject類。

class GCObject

{

??? //friend class DND::Mempool;

??? template<classT>

??? friend classDND::PoolArray;

public:

??? unsigned GetRefNum()

??? {

??????? return m_refNum;

??? }

??? void PrintTypeName()

??? {

??????? std::cout<< typeid(this).name()<< std::endl;

??? }

??? unsigned m_refNum;

??? GCObject() : m_refNum(0){}

??? virtual booloperator<(const GCObject& b)

??? {

??????? return true;

??? }

};

??? GCObject類主要包含引用計數變量,使用此框架的類都應該繼承它。DND_GC_CLASS宏就讓參數繼承它,并為其生成一個H開頭的句柄類。

#define DND_GC_CLASS(ClassName)\

class ClassName;\

class H##ClassName\

{\

public:\

??? ClassName* operator->(){assert(m_p &&"This is null reference!"); return (ClassName*)m_p;}\

??? ~H##ClassName(){if(m_p&& !--m_p->m_refNum){m_p = 0;}}\

??? H##ClassName(): m_p(0){}\

??? H##ClassName(constH##ClassName&b){m_p = (GCObject*)b.m_p;++m_p->m_refNum;}\

??? H##ClassName&operator=(constH##ClassName& b){if(m_p&& !--m_p->m_refNum){m_p = 0;}m_p = (GCObject*)b.m_p;++m_p->m_refNum;return *this;}\

??? bool operator<(constH##ClassName& b){return *m_p < *b.m_p;}\

??? void Initalize(){if(m_p && !--m_p->m_refNum){m_p = 0;} m_p = (GCObject*)DND::Mempool::GetSite<ClassName>();}\

private:\

??? GCObject* m_p;\

??? static void*operator new(size_tsize){};\

??? static voidoperator delete(void*ptr){};\

};\

class ClassName : privateGCObject\

{\

??? friend classH##ClassName;\

最后我做了一下測試,對比了和直接new/delete的速度差距:

??????? DWORD t1 = GetTickCount();

??????? unsigned i =REPLAY_COUNT;

??????? while (i--)

??????? {

??????????? //STU_NUMBER

??????????? HStudent stu3[STU_NUMBER];

??????????? for (unsignedi = 0; i != STU_NUMBER; ++i)

??????????? {

??????????????? stu3[i].Initalize();

??????????????? //stu3[i]->Print();

??????????? }

??????? }

??????? DWORD t2 = GetTickCount();

??????? std::cout<< "花費時間:"<< t2 - t1? << "ms"<< std::endl;

??????? //

??????? t1 = GetTickCount();

??????? i = REPLAY_COUNT;

??????? while (i--)

??????? {

??????????? Student* stu4 = new Student[STU_NUMBER];

??????????? delete stu4;

??????? }

??????? t2 = GetTickCount();

??????? std::cout<< "花費時間:"<< t2 - t1 << "ms"<< std::endl;

得出的數據如下:

?

作者:略游

日期:17-07-22

QQ:1339484752

總結

以上是生活随笔為你收集整理的C++简单实现GC和内存池的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。