一、通用内存池
1.通用内存池的实现过程:
(1)通用内存池为需要申请空间的类提供两个公用接口,通过调用alloc接口先申请一块连续的内存空间,该段内存空间能够容纳一定数量的对象;
(2)每个对象连同一个指向下一个对象的指针一起构成一个内存节点(Node)。以静态链表的形式管理开辟好的内存,各个空闲的内存节点通过指针形成一个链表,链表的每一个内存节点都是一块可供()分配的内存空间;
(3)某个内存节点一旦分配出去,从未使用内存节点链表中去除;
(4)一旦释放了某个内存节点的空间,又将该节点重新加入空闲内存节点链表;
(5)如果一个内存块的所有内存节点分配完毕,若程序继续申请新的对象空间,则会再次申请一个内存块来容纳新的对象。新申请的内存块会加入内存块链表中。
2.通用内存池的优点:
(1)内存池不依赖某个类存在。
(2)本文中实现了单例模式的内存池,(考虑了线程安全问题)
针对内存池中的每一个资源进行组织结构,要想申请内存,先得知道mdata的数据类型,其次得知道指针域指向哪里。
class Node//嵌套的Node类,表示内存池的数据结构
{
public:
T mdata;//相当于 char mdata[sizeof(T)]
Node* pnext;
public:
Node():pnext(NULL){}
};
内存池提供两个公用接口alloc,dealloc,使得其他类中的new和delete摆脱对类的依赖,即实现了一个通用的内存池。
void* alloc(size_t size);
void dealloc(void* ptr);
实现内存自主管理,以链表方式实现,以静态指针标志未使用部分的 起始位置。
完整代码如下:(其中以stu类为例进行使用内存池)
#include <iostream>
const int MEMORY_POOL_SIZE =10;
template<typename T>
class Memory_Pool//内存池类
{
public:
static Memory_Pool<T>* getInstance()//单例模式,提供生成唯一对象的接口,返回引用或指针,是一个静态接口。
{
return &mpool;
}
void* alloc(size_t size)
{
if(pool == NULL)//每次先判断当前是否有可用资源,有资源直接返回可用资源,没资源则申请一整块资源备用
{
pool = new Node[MEMORY_POOL_SIZE]();
Node* pCur = pool;
for(pCur;pCur<pool+MEMORY_POOL_SIZE-1;pCur=pCur+1)//利用静态链表的形式实现一个内存池
{
pCur->pnext = pCur+1;
}
pCur->next =NULL;
}
Node* prt =pool;
pool=pool->pnext;
return prt;
}
void dealloc(void* ptr)//把不用的资源重新加入到未使用部分的链表中
{
Node* mptr =(Node*)ptr;
mptr->pnext=pool;
pool=mptr;
}
private:
//因为要实现一个单例模式的内存池所以此处的构造和拷贝构造没有实现的意义
Memory_Pool(){}//构造函数为空函数
Memory_Pool(const Memory_Pool<T>&);//拷贝构造声明
class Node//嵌套的Node类,表示内存池的数据结构
{
public:
T mdata;//相当于 char mdata[sizeof(T)]
Node* pnext;
public:
Node():pnext(NULL){}
};
static Node* pool;
static Memory_Pool<T> mpool;
};
template<typename T>
Memory_Pool<T> Memory_Pool<T>::mpool;//生成唯一内存池的对象
template<typename T>
typename Memory_Pool<T>::Node*Memory_Pool<T>::pool = NULL;
//===================================================================//
class Stu//stu类
{
public:
Stu(int id = int(), int age = int(), float score = float()) :
mid(id), mage(age), mscore(score){}
void* operator new(size_t size)
{
return ppool->alloc(size);//调用内存池类的接口alloc
}
void operator delete(void* ptr)
{
ppool->dealloc(ptr);//调用内存池类的接口dealloc
}
private:
int mid;
int mage;
float mscore;
static Memory_Pool<Stu>* ppool;//把内存池的一个对象作为stu的静态成员
friend std::ostream& operator<<(std::ostream&, const Stu&);
friend std::istream& operator>>(std::istream&, Stu&);
};
Memory_Pool<Stu>* Stu::ppool = Memory_Pool<Stu>::getInstance();//调用静态接口
std::ostream& operator<<(std::ostream& out, const Stu& rhs)//stu类的输出流重载
{
out << rhs.mid << " ";
out << rhs.mage << " ";
out << rhs.mscore << " ";
return out;
}
std::istream& operator>>(std::istream& in, Stu& rhs)//stu类的输入流重载
{
in >> rhs.mid;
in >> rhs.mage;
in >> rhs.mscore;
return in;
}
//=====================================================================//
int main()
{
Stu* pstu1 = new Stu(1, 20, 98.5);
Stu* pstu2 = new Stu(1, 20, 98.5);
Stu* pstu3 = new Stu(1, 20, 98.5);
//delete pstu1;
delete pstu2;
//delete pstu3;
Memory_Pool<Stu>* mp1 = Memory_Pool<Stu>::getInstance();
Memory_Pool<Stu>* mp2 = Memory_Pool<Stu>::getInstance();
Memory_Pool<Stu>* mp3 = Memory_Pool<Stu>::getInstance();
std::cout << *pstu1 << std::endl;
return 0;
}
结果如图:
二、智能指针
实现内存的自主管理,c++没有内存自动回收机制。
要解决内存自主管理这一问题,解决办法为:自主开辟-------系统释放。
让内存块被一个智能指针的对象所管理,智能指针对象的生成就是把一块内存交给智能指针对象管理。智能指针对象的销毁就是由系统调用析构函数,析构函数调用delete操作,从而达到系统释放的目的。
template<typename T>
class SmartPtr
{
public:
SmartPtr(T* ptr = NULL) :mptr(ptr){}//智能指针只是管理,没必要实心深拷贝
~SmartPtr()//析构函数由系统调用
{
delete mptr;//让系统调用析构时执行delete操作
}
T& operator*()//解引用运算符重载使得智能指针可以跟普通指针执行同样的操作
{
return *mptr;
}
T* operator->()//指向运算符重载使得智能指针可以跟普通指针执行同样的操作
{
return mptr;
}
private:
T* mptr;
};
class Test
{
public:
Test(int a) :ma(a){}
void Show()
{
std::cout << ma << std::endl;
}
public:
int ma;
float mb;
};
int main()
{
int* p = new int;
*p = 20;
SmartPtr<int> sp1(new int);
*sp1 = 20;//相当于sp1.operator*() = 20;
Test* pt = new Test(20);
pt->Show();
pt->ma = 20;
pt->mb = 30;
SmartPtr<Test> sp2(new Test(30));
sp2->Show(); //sp2.operator->() // Test* mptr->Show();
sp2->ma = 20;//sp2.operator->() // mptr->ma
sp2->mb = 30;
return 0;
}