使用自定义分配器调用对象构造函数/析构函数

时间:2012-04-18 00:42:24

标签: c++ memory memory-management new-operator

我一直在研究自定义分配器,我经常看到它们使用某种功能来分配内存。出于测试目的并进一步教育我自己,我试图做出一个“简单”的例子。但是,我对如何做有一个基本的了解。 mallocnew的主要区别之一是,新的构造函数被调用。如果我想编写一个本质上替换new的自己的分配器怎么办?在使用malloc时如何调用构造函数?

我理解在类上我可以为类重载newdelete,所以我想问题的一个重要部分是new在分配期间如何调用对象构造函数?同样,我对delete如何调用析构函数感兴趣。

我创建了一个示例测试代码,我希望在分配期间调用SomeClass构造函数,但我不知道如何。

#include <malloc.h>

void* SomeAllocationFunction(size_t size) {
    return malloc(size);
}

class SomeClass
{
public:
    SomeClass() {
        int con = 1000;
    }

    ~SomeClass() {
        int des = 80;
    }
};

int main(void){
    SomeClass* t = (SomeClass*)SomeAllocationFunction(sizeof(SomeClass));
    return 0;
}

(注意,我知道我可以使用new。但是,出于学习的目的,我正在尝试创建一个不只是调用new或{{1}的自定义分配器})。

3 个答案:

答案 0 :(得分:13)

本质上,当你使用像T *t = new T;这样的新表达式时,它大致相当于:

void *temp = operator new(sizeof(T));
T *t = new(temp) T;

因此,首先使用分配函数分配一些原始内存,然后在该内存中构造一个对象。同样,当您使用删除表达式时:delete t;,它大致等同于:

t->~T();
operator delete(t);

因此,如果您为特定类重载newdelete

class T { 
    int data; 
public:
    // I've made these static explicitly, but they'll be static even if you don't.
    static void *operator new(size_t size) { 
        return malloc(size);
    }
    static void operator delete(void *block) { 
        free(block);
    }
};

然后当你使用一个新表达式时,它会调用类“operator new来分配内存,然后调用malloc,这样T *t = new T();将最终通过分配内存malloc(同样,当你delete时,它会使用operator delete,它会调用free

至少在通常使用的术语中,分配器非常相似,除了它被容器而不是其他代码使用。它还将分配函数和删除函数封装到一个类中,因此当您将一个函数传递给容器时,您只需要传递一个对象,并且分配和删除函数几乎不会出现不匹配的情况。

暂时忽略有关用于事物的名称的详细信息,标准库中的Allocator类大致相同,所以稍微重命名{{{ 1}}上面的类,你将完成写一个标准分配器的一半。为了配置和删除,它有一个函数T一些内存(将内存块更改为另一种类型),创建一个到位的对象(基本上只是一个新的贴图包装)并销毁一个对象(再次,在析构函数调用周围的简单包装)。当然,它使用rebindoperator new代替operator deletemalloc,就像我上面使用的那样。

答案 1 :(得分:8)

使用新的展示位置,您可以将已分配的内存位置传递给新运算符。然后new将在给定的位置构造对象,而不对其自身进行分配。

编辑:

这是如何实施的:

int main(void){
    // get memory
    void * mem_t = SomeAllocationFunction(sizeof(SomeClass));
    // construct instance
    SomeClass* t = new(mem_t) SomeClass;

    // more code

    // clean up instance
    t->~SomeClass();
    return 0;
}

答案 2 :(得分:0)

要获取要调用的构造函数,请使用placement new(注意,您不能覆盖新的贴图)。删除和所有陷阱the FAQ does a good job of explaining it.