一:嵌入式指针(embedded pointer)
1、嵌入式指针概念
一般应用在内存池相关的代码中,成功使用嵌入式指针有个前提条件:(类A对象的sizeof必须不小于4字节)
嵌入式指针工作原理:借用A对象所占用的内存空间中前4个字节,这4个字节用来链住这些空闲的内存块;但是,一旦某一块被分配出去,那么这个块的前4个字节就不再需要,此时这4个字节可以被正常使用。
2、嵌入式指针演示代码
sizeof()超过4字节的类就可以安全的使用嵌入式指针(×64指针是8位)。
#include <iostream>
using namespace std;
class TestEP
{
public:
int m_i;
int m_j;
int m_k;
int m_l;
public:
struct obj //结构
{
//成员,是个指针
struct obj* next; //这个next就是个嵌入式指针
//自己是一个obj结构对象,那么把自己这个对象的next指针指向另外一个obj结构对象,
//最终,把多个自己这种类型的对象通过链串起来
};
};
void func()
{
TestEP mytest;
cout << sizeof(mytest) << endl; //8
TestEP::obj* ptemp; //定义一个指针
ptemp = (TestEP::obj*)&mytest; //把对象mytest首地址给了这个指针ptemp,这个指针ptemp指向对象mytest首地址
cout << sizeof(ptemp->next) << endl; //4
cout << sizeof(TestEP::obj) << endl; //4
ptemp->next = nullptr;
}
struct test
{
public:
test* pt;
};
int main()
{
func();
}
TestEP mytest;
cout << sizeof(mytest) << endl; //8
TestEP::obj* ptemp; //定义一个指针
ptemp = (TestEP::obj*)&mytest; //把对象mytest首地址给了这个指针ptemp,这个指针ptemp指向对象mytest首地址
&mytest 0x000000facff3f768 {m_i=-858993460 m_j=-858993460 m_k=-858993460 …}
&ptemp 0x000000facff3f798 {0x000000facff3f768 {next=0xcccccccccccccccc {next=??? }}}
&ptemp->next 0x000000facff3f768 {0xcccccccccccccccc {next=??? }}
ptemp->next = nullptr;
&ptemp 0x000000facff3f798 {0x000000facff3f768 {next=0x0000000000000000 }}
&(ptemp->next) 0x000000facff3f768 {0x0000000000000000 }
二:内存池代码的改进
单独的为内存池技术来写一个类
#include <iostream>
using namespace std;
//专门的内存池类
class MyAllocator //必须保证应用本类的sizeof()不少于4字节,否则会崩溃或者报错
{
public:
//分配内存接口
void* allocate(size_t size)
{
obj* tmplink;
if (m_freePosition == nullptr)
{
//为空,要申请一大块内存
size_t realsize = m_sTrunkCount * size; //申请m_sTrunkCount这么多倍的内存
m_freePosition = (obj*)malloc(realsize);
tmplink = m_freePosition;
//把分配出来的这一大块内存(5小块),彼此链起来,供后续使用
for (size_t i = 0; i < m_sTrunkCount - 1; i++)
{
tmplink->next = (obj*)((char*)tmplink + size);
tmplink = tmplink->next;
}
tmplink->next = nullptr;
}
tmplink = m_freePosition;
m_freePosition = m_freePosition->next;
return tmplink;
}
//释放内存接口
void deallocate(void* phead)
{
((obj*)phead)->next = m_freePosition;
m_freePosition = (obj*)phead;
}
private:
//写在类内的结构,这样只让其在类内使用
struct obj
{
struct obj* next; //这个next就是个嵌入式指针
};
int m_sTrunkCount = 5; //一次分配5倍的该类内存作为内存池的大小
obj* m_freePosition = nullptr;
};
//------------------------------------------
#define DECLARE_POOL_ALLOC()\
public:\
static MyAllocator myalloc;\
static void* operator new(size_t size)\
{\
return myalloc.allocate(size);\
}\
static void operator delete(void* phead)\
{\
return myalloc.deallocate(phead);\
}\
//------------------------------------------
#define IMPLEMENT_POOL_ALLOC(classname)\
MyAllocator classname::myalloc;
//------------------------------------------
class A
{
public:
int m_i;
int m_j; //为了保证sizeof(A)凑够4字节,偃师市
public:
DECLARE_POOL_ALLOC();
};
IMPLEMENT_POOL_ALLOC(A);
void func()
{
A* mypa[100];
for (size_t i = 0; i < 15; i++)
{
mypa[i] = new A();
mypa[i]->m_i = 10;
mypa[i]->m_j = 20;
printf("%p\n", mypa[i]);
}
for (size_t i = 0; i < 15; i++)
{
delete mypa[i];
}
}
int main()
{
func();
}