11

私はカスタム アロケータを調査してきましたが、何らかの関数を使用してメモリを割り当てることがよくあります。テストの目的と自分自身をさらに教育するために、そのための「簡単な」例を作成しようとしました。ただし、その方法について私が理解している基本的なことが 1 つあります。mallocvsの主な違いの 1 つは、newnew ではコンストラクターが呼び出されることです。本質的に を置き換える独自のアロケータを作成したい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;
}

(メモとして、私は単に使用できることを知っています。ただし、学習の目的で、 ornewを呼び出すだけではないカスタム アロケーターを作成しようとしています)。newplacement new

4

3 に答える 3

16

本質的に、次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)。

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

今のところ、物事に使用されている名前の詳細を無視すると、標準ライブラリのAllocatorクラスはほとんど同じことを行うので、上記のクラスの関数の名前を少し変更するだけで、T約半分の書き込みが完了します。標準アロケータ。割り当てと削除を行うために、rebindメモリへの機能(メモリのブロックを別のタイプに変更)、オブジェクトの作成(基本的には新しい配置のラッパー)、オブジェクトの破棄(ここでも簡単なラッパー)があります。デストラクタ呼び出しの周り)。もちろん、それは私が上で使用したようにoperator newoperator deleteの代わりにmallocを使用します。free

于 2012-04-18T02:47:15.117 に答える
9

配置 new を使用すると、既に割り当てられているメモリ位置を new オペレーターに渡すことができます。次に、 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;
}
于 2012-04-18T00:53:50.177 に答える
0

コンストラクターを呼び出すには、placement new を使用します (placement new をオーバーライドできないことに注意してください)。削除とすべての落とし穴については、FAQ がうまく説明しています。

于 2012-04-18T01:27:51.253 に答える