任务需求
传统的对象创建是依赖malloc函数或者new关键字申请堆内存,然后在堆内存上创建的。但是我们嫌弃这样频繁的让系统为我们分配内存的方式太慢太繁琐了.
现在我们需要写一个简易的内存池,在内存池中提前分配好一些内存,后续使用定位new的方式在内存池中创建对象,又因为对象的类型是不确定的,为了能方便对象的析构,所以我们需要维护一个链表,链表中存放对象和指向能调用对象析构函数的函数的函数指针. 后续我们只需要遍历一遍链表,然后就可以通过函数指针将对象一一析构.实现一个简易的内存池-对象的构造与析构.
分析
定位new
定位new的使用方式:
T * p = new(buffer) T;
定位new与普通new的区别就是定位new是指定一个内存,在指定的内存上进行对象的创建,而普通new是遍历整个堆区找到一个合适的内存块.
所以定位new常跟内存池连用
is_trivially_destructible::value
用于检查一个类是不是易于销毁的,如果是易于销毁的(只有默认的析构函数)则返回true,否则返回false.
这个函数是帮助我们检测创建的对象,需不需要通过析构函数进行销毁,如果需要,我们就把对应的函数指针放入链表中,然后统一使用函数指针将所有之前创建的对象一一销毁
完整代码
这段代码并不是完美的,仅供参考学习定位new和内存池
#include<iostream>
using namespace std;
class Node
{
size_t offset;
const int max_size;
char* header_p = nullptr;
public:
Node(int size) :max_size(size)
{
header_p = (char*)malloc(max_size);
offset = 0;
}
~Node()
{
if (header_p != nullptr)
{
delete(header_p);
header_p = nullptr;
}
}
unsigned char* allocate(size_t size)
{
if (size + offset >= max_size)
{
cout << "error";
return nullptr;
}
cout << "内存的起始位置:" << offset << " ";
cout << "内存的结束位置:" << size + offset << endl;
unsigned char* ans = (unsigned char*)(header_p + offset);
offset = offset + size;
return ans;
}
void deallocate()
{
offset = 0;
}
};
#define CLASS_FUNCTION static
template<typename T>
struct wrapper_t
{
CLASS_FUNCTION void func(void* p)
{
cout << "正在析构" << endl;
((T*)p)->~T();
cout << "析构成功" << endl;
}
};
class Link
{
private:
struct link_list_node
{
struct link_list_node* next;
void* obj;
void(*dtor_fun)(void*);
};
Node* alloc;
link_list_node* Head_node = nullptr;
link_list_node* Tail_node = nullptr;
link_list_node* First_node = nullptr;
public:
Link()
{
alloc = new Node(1024);
link_list_node* mynode = new link_list_node();
Head_node = mynode;
Tail_node = mynode;
First_node = mynode;
}
template<typename T>
T* create_obj(int size)
{
T* myobj = new(alloc->allocate(size))T;
if (!is_trivially_destructible<T>::value)
{
link_list_node* pDtorRecoder = (link_list_node*)malloc(sizeof(link_list_node));
pDtorRecoder->dtor_fun = wrapper_t<T>::func;
pDtorRecoder->obj = myobj;
Tail_node->next = pDtorRecoder;
Tail_node = Tail_node->next;
}
return myobj;
}
void del_all_obj()
{
while (Head_node != nullptr)
{
if (Head_node != First_node)
{
Head_node->dtor_fun(Head_node->obj);
}
if (Head_node == Tail_node)
{
break;
}
else
Head_node = Head_node->next;
}
alloc->deallocate();
Head_node = First_node;
Tail_node = First_node;
}
};
class MYCLASS
{
int a;
char b;
};
int main()
{
Link test;
test.create_obj<int>(10);
test.create_obj<char>(20);
test.create_obj<double>(30);
test.del_all_obj();
test.create_obj<string>(10);
test.create_obj<string>(10);
test.del_all_obj();
test.create_obj<int>(10);
test.create_obj<MYCLASS>(sizeof(MYCLASS));
}