我一直在研究自定义分配器,我经常看到它们使用某种功能来分配内存。出于测试目的并进一步教育我自己,我试图做出一个“简单”的例子。但是,我对如何做有一个基本的了解。 malloc
与new
的主要区别之一是,新的构造函数被调用。如果我想编写一个本质上替换new
的自己的分配器怎么办?在使用malloc
时如何调用构造函数?
我理解在类上我可以为类重载new
和delete
,所以我想问题的一个重要部分是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}的自定义分配器})。
答案 0 :(得分:13)
本质上,当你使用像T *t = new T;
这样的新表达式时,它大致相当于:
void *temp = operator new(sizeof(T));
T *t = new(temp) T;
因此,首先使用分配函数分配一些原始内存,然后在该内存中构造一个对象。同样,当您使用删除表达式时:delete t;
,它大致等同于:
t->~T();
operator delete(t);
因此,如果您为特定类重载new
和delete
:
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
一些内存(将内存块更改为另一种类型),创建一个到位的对象(基本上只是一个新的贴图包装)并销毁一个对象(再次,在析构函数调用周围的简单包装)。当然,它使用rebind
和operator new
代替operator delete
和malloc
,就像我上面使用的那样。
答案 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.