2012-04-18 94 views
8

我一直在寻找自定义分配器,并且我经常看到它们使用某种函数来分配内存。为了测试的目的,并进一步教育我的自我,我试图做一个“简单”的例子。但是,我知道如何去做一件基本的事情。 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。然而,对于学习的目的,我想创建一个自定义分配器,不只是叫newplacement new)。

回答

10

从本质上讲,当你使用一个新的表达方式,如:T *t = new T;,这大致相当于:

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

因此,首先它分配使用分配函数的一些原始内存,那么它会在该内存中构造一个对象。同样,当你使用delete表达式,如: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,它将使用wi将会拨打free)。

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

忽略,就目前而言,关于使用什么名称的东西的细节,在标准库中allocator类大多不相同,所以用在T类以上的功能有点重命名,你”在编写标准分配器时大约有一半时间完成。去分配和删除,它有一个功能,以rebind某些内存(将内存块更改为另一种类型),创建一个对象(基本上只是一个位置新的包装)并摧毁一个对象(再次,平凡包装析构函数调用)。当然,它使用operator newoperator delete,而不是像上面所用的mallocfree

+0

如果placement new是我需要使用的,那么为什么例如MSVC的'new'不会在其new'版本中调用放置new(在new.cpp中,您可以通过进入一个新调用来获取它)。 – mmurphy 2012-04-18 03:03:30

+0

@mmurphy:*粗略*相似,绝对不相同。 – 2012-04-18 04:54:02

7

使用新的布局,您可以将已分配的内存位置传递给新操作员。然后新的将在给定的地方构造对象而不对其自身进行分配。

编辑:

这是它如何实现:

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

海报说他不想叫新的。 – josephthomas 2012-04-18 00:55:44

+4

构造函数没有名称(与析构函数相对),因此不能直接调用它们。如果您希望它占据给定的内存位置,则放置new是正确构造类实例的唯一方法。 – bjhend 2012-04-18 01:25:58

+2

我没有使用新的具体问。 – mmurphy 2012-04-18 01:52:57

0

要获得构造函数被调用你用放置新的(注意不能覆盖放置新)。对于删除和所有的陷阱以及the FAQ does a good job of explaining it.

+1

中调用'placement new',我没有使用新的特殊问题。 – mmurphy 2012-04-18 01:51:49

+0

是的,但放置new是一种语言原语,没有办法在语言中实现它。 – stonemetal 2012-04-22 01:05:11

+1

@stonemetal:Placement-new不是一种语言原语,即'void * operator new(size_t bytes,void * place){return place; }' – ulatekh 2014-05-28 16:20:34

相关问题