什么是内存池?
当我们使用new或者malloc申请内存的时候会调用系统调用,这样就会进行用户态到内核态的切换,如果频繁进行内存申请就会造成频繁的用户态内核态之间的切换,从而导致程序效率低下。
我们可以事先申请一块很大的内存,称之为内存池,之后每次申请就从内存池中申请,释放就又还给内存池,只有当内存池中的内存用光之后再继续向系统申请,这样可以大大减少用户态和内核态之间的转换,从而提高程序的效率。
如何实现内存池?
假设我们要实现一个队列类Mqueue,在入队出队时需要连续的申请释放内存。我们可以引入内存池。
- 在Mqueue类中定义一个内存池类space,将其设置为单例模式(因为内存池只有一个,不能创建一个队列对象就创建一个内存池,这样就失去了内存池存在的意义),space在构造的时候创建出一块有较多数量队列结点类型的内存。
- 在Mqueue类中还有一个队列节点Node类,在该类中重载了new 和 delete方法,保证每次申请释放内存都在内存池中进行。
代码实现
# include<iostream>
# include<vector>
# define LEN 10
using namespace std;
template<typename T>
class Mqueue
{
public:
class Node;
Mqueue()
{
_head = new Node();
_head->_next = NULL;
_tail = _head;
}
~Mqueue()
{
Node *p = _head->_next;
while (_head != _tail)
{
delete(_head);
_head = p;
p = p->_next;
}
delete(_head);
}
void push(T val)
{
Node *p = new Node(val);
p->_next = NULL;
_tail->_next = p;
_tail = p;
}
void pop()
{
if (isEmpty())
{
throw "queue is empty";
}
Node *p = _head->_next;
_head->next = p->_next;
if (_head->_next == NULL)
{
_tail = _head;
}
delete(p);
}
T top()
{
return _head->_next->_val;
}
bool isEmpty()
{
if (_head == _tail)
{
return true;
}
else
{
return false;
}
}
private:
class space
{
public:
static space* getSpace()//设置为单例模式
{
if (NULL == _space)
{
_space = new space();
}
return _space;
}
private:
space()
{
Node* tmp = new Node[LEN];
int i = 0;
for (; i < LEN - 1; i++)
{
tmp[i]._next = &tmp[i + 1];
}
tmp[i]._next = NULL;
_pool = &tmp[0];
}
static space* _space;
Node* _pool;
friend class Node;
};
class Node
{
private:
T _val;
Node *_next;
static space* _space;
public:
Node()
{
_next = NULL;
}
Node(T val)
{
_val = val;
_next = NULL;
}
void *operator new(size_t size)
{
cout << "void *operator new(size_t size)" << endl;
if (_space->_pool == NULL)
{
Node *tmp = new Node[LEN];
int i = 0;
for (; i < LEN - 1; i++)
{
tmp[i]._next = &tmp[i + 1];
}
tmp[i]._next = NULL;
_space->_pool = &tmp[0];
}
Node* mem = _space->_pool;
_space->_pool = _space->_pool->_next;
return mem;
}
void operator delete(void *p)
{
cout << "void operator delete(void *p)" << endl;
Node *tmp = (Node*)p;
tmp->_next = _space->_pool;
_space->_pool = tmp;
}
friend class Mqueue;
};
Node *_head;
Node *_tail;
};
template<typename T>
typename Mqueue<T>::space* Mqueue<T>::Node::_space = Mqueue<T>::space::getSpace();
template<typename T>
typename Mqueue<T>::space* Mqueue<T>::space::_space = NULL;
int main()
{
Mqueue<int> q1;
for (int i = 0; i < 10; i++)
{
q1.push(i);
}
cout << q1.top() << endl;
return 0;
}