allocator类
class allocator {
private:
struct obj {
struct obj* next;
};
public:
void* allocate(size_t);
void deallocate(void*, size_t);
private:
obj* freeStore = nullptr;
const int CHUNK = 5;
};
void* allocator::allocate(size_t size) {
obj* p;
if (!freeStore) {
size_t chunk = CHUNK * size;
freeStore = p = (obj*)malloc(chunk);
for (int i = 0; i < (CHUNK - 1); ++i) {
p->next = (obj*)((char*)p + size);
p = p->next;
}
p->next = nullptr;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void allocator::deallocate(void* p, size_t) {
((obj*)p)->next = freeStore;
freeStore = (obj*)p;
}
class Foo {
public:
long a;
double b;
static allocator myAlloc;
public:
Foo(long x): a(x) {}
static void* operator new(size_t size) {
return myAlloc.allocate(size);
}
static void operator delete(void* pdead, size_t size) {
return myAlloc.deallocate(pdead, size);
}
};
allocator Foo::myAlloc;
Foo
中每次调用operator new
都会调用allocate
,但allocate
并不是每次都分配内存,而是第一次调用的时候一下子就分配一大块,这里是分配5个Foo
,这样,后面再调用operator new
的时候就不用再分配内存了,而是直接从内存池中获取
这样同一块内存池中的两个对象就是直接相邻,没有头尾cookie
这里用到了嵌入式指针的思想,即内存未分配出去之前,拿出8字节来保存指向下一个内存的指针,分配出去后,整个内存就是类的对象了,这个时候也不需要指针了,等回收内存的时候,不再使用类对象了,就又还原成指针了
int main() {
Foo *p[100];
cout << sizeof(Foo) << endl;
for (int i = 0; i < 10; i++) {
p[i] = new Foo(i);
cout << p[i] << ' ' << p[i]->a << endl;
}
for (int i = 0; i < 10; i++) {
delete p[i];
}
return 0;
}
// 16
// 0x559b42e3b280 0
// 0x559b42e3b290 1
// 0x559b42e3b2a0 2
// 0x559b42e3b2b0 3
// 0x559b42e3b2c0 4
// 0x559b42e3b2e0 5
// 0x559b42e3b2f0 6
// 0x559b42e3b300 7
// 0x559b42e3b310 8
// 0x559b42e3b320 9
可以看到一个对象占用了16字节
如果不使用allocator
class Foo {
public:
long a;
double b;
public:
Foo(long x): a(x) {}
};
int main() {
Foo *p[100];
cout << sizeof(Foo) << endl;
for (int i = 0; i < 10; i++) {
p[i] = new Foo(i);
cout << p[i] << ' ' << p[i]->a << endl;
}
for (int i = 0; i < 10; i++) {
delete p[i];
}
return 0;
}
// 16
// 0x5633e46ad280 0
// 0x5633e46ad2a0 1
// 0x5633e46ad2c0 2
// 0x5633e46ad2e0 3
// 0x5633e46ad300 4
// 0x5633e46ad320 5
// 0x5633e46ad340 6
// 0x5633e46ad360 7
// 0x5633e46ad380 8
// 0x5633e46ad3a0 9
可以看到两个对象之间相差32字节,也就是一个对象实际占用了32字节,其中中间的16字节是类的成员,前后的两个8字节是cookie