2012-04-18 7 views
8

私はカスタムアロケータを調べていましたが、何らかの種類の関数を使ってメモリを割り当てることがよくあります。テスト目的のために、私の自己をさらに教育するために、私はそうする簡単な例を作りました。しかし、私のやり方について理解している基本的なことが1つあります。 mallocnewの主な違いの1つは、newを使用するとコンストラクタが呼び出されることです。基本的に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またはplacement newを呼び出さないカスタムアロケータを作成しようとしています学習の目的のために知っています)。

答えて

10

について本質的には、:T *t = new T;を、それはほぼ同等だ:だから

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

、最初のそれは、割り当て機能を使用して、いくつかの生のメモリを割り当て、そのメモリ内にオブジェクトを構築します。あなたのようなdelete式を使用する場合同様に、:あなたが特定のクラスのためにnewdeleteをオーバーロードする場合、

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

ので:次に

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); 
    } 
}; 

新しい使用する場合delete t;、それはほぼ同等です式を呼び出すと、クラス 'operator newがメモリを割り当てるために呼び出され、mallocが呼び出されるため、を介してメモリを割り当てることになります(同様に、deleteの場合はoperator deleteを使用します).wi電話番号:free

少なくとも、通常は用語が使用されているので、アロケータは、他のコードの代わりにコンテナで使用される点を除いて、非常に似ています。また、割り当て関数と削除関数をクラスにカプセル化するので、コンテナに渡すときにオブジェクトを1つだけ渡すだけで、割り当て関数と削除関数が一致しない可能性はほとんどありません。

無視して、一瞬のために、物事のために使用されているものの名​​前についての詳細は、標準ライブラリのアロケータクラスほとんど、同じことを上記Tクラスの機能のほとんどない名前の変更とそう、あなた」標準的なアロケータを書いたのは約半分です。割り当てと削除を行うには、rebindいくつかのメモリ(メモリのブロックを別のタイプに変更する)、場所にオブジェクトを作成する(基本的に新しい配置のラッパー)、オブジェクトを破棄するデストラクタ呼び出しの周りのラッパー)。もちろん、私は上記のようにmallocfreeの代わりにoperator newoperator deleteを使用します。

+0

もし私が使用する必要があるプレースメントが新しい場合、MSVCの' new'はnew.cppのバージョンで新しいプレースメントを呼び出しません(new.cppでは新しい呼び出しを行うことでそれを得ることができます)。 – mmurphy

+0

@mmurphy:*概ね*と似ていますが、確かに同じではありません。 –

7

新しい配置では、すでに割り当てられたメモリ位置を新しい演算子に渡すことができます。次に、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

ポスターは新しく電話したくないと言った。 – josephthomas

+4

コンストラクタは名前を持たず(デストラクタとは反対)、直接呼び出すことはできません。特定のメモリ位置を占有したい場合は、クラスインスタンスを適切に構築する唯一の方法です。 – bjhend

+2

私は特に新しいものを使用せずに尋ねました。 – mmurphy

0

新しい配置を使用呼び出されるコンストラクタを取得するには:

これは、それを実現することができる方法です。あなたのような新しい表現を使用する場合、削除し、すべての落とし穴もthe FAQ does a good job of explaining it.

+1

newを使用せずに具体的に質問しました。 – mmurphy

+0

はい、ただし、プレースメントnewは言語プリミティブです。言語で実装する方法はありません。 – stonemetal

+1

@stonemetal:Placement-newは言語プリミティブではありません。つまり、 'void * operator new(size_t bytes、void * place){return place; } ' – ulatekh

関連する問題