2012-04-18 164 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

相關問題