玩命加载中 . . .

内存管理


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


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录