1

こんにちは、事前に割り当てられたメモリを使用してオブジェクトと配列を作成して実験しています。たとえば、次のコードがあります。

int * prealloc = (int*)malloc(sizeof(Test));

Test *arr = new(prealloc) Test();

test は次のように定義されます。

class Test {
public:
    Test() {
        printf("In Constructor\n");
    }
    ~Test() {
        printf("In Destructor\n");
    }

    int val;
};

このシナリオで delete を呼び出すと、実際には悪いメモリが解放されます。b/c 何らかのタイプのメモリ マネージャーを使用している可能性があるため、問題が発生することは間違いありません。私はインターネットで検索しましたが、見つけた唯一の解決策は、デストラクタを明示的に呼び出してから無料で呼び出すことでした:

arr->~Test();
free(arr);

これを行う別の方法はありますか?おそらくdeleteを呼び出して、デストラクタを呼び出すだけでメモリを解放しないように指示する方法はありますか?

私の2番目の問題は、前の例のように、新しい事前割り当てメモリに渡すことができる配列を操作するときでした:

int * prealloc2 = (int*)malloc(sizeof(Test) * 10);
Test *arr2 = new(prealloc2) Test[10];

呼び出すdelete[]と、配列内の各要素のデストラクタが呼び出されるだけでなく、望ましくないメモリも解放されます。実行する必要があることがわかった唯一の方法は、配列を調べてデストラクタを明示的に呼び出してから、free を呼び出すことです。通常の none 配列演算子と同様に、メモリを解放せずにデストラクタを呼び出すように演算子に指示する方法はありますか?

私が気づいたことの 1 つは、配列の new 演算子が実際には配列のサイズを格納するために最初の 4 バイトを使用することでした (私はこれを 32 ビット ビルドのビジュアル スタジオでのみテストしました)。配列にはありますが、まだ 1 つの問題があります。配列がポインター配列の場合はどうなりますか? 例えば:

Test **arr2 = new Test*[10];

誰かがこれらの質問で私を助けてくれませんか。

4

3 に答える 3

5

配置 new で作成したオブジェクトを破棄するためにデストラクタを直接呼び出すことは正常であり、期待されています。他の方法に関して言えば、Allocator オブジェクトを使用するのが唯一の明白な代替手段です (少なくとも 99% の確率で、placement new のラッパーであり、デストラクタを直接呼び出すだけです)。

一般的に言えば、まったく使いたくないnew[]でしょう。operator new通常、生メモリを(またはおそらく)で割り当て::operator new、一致するoperator deleteまたはで解放し::operator deleteます。

そのメモリに新しい配置でオブジェクトを作成し、デストラクタを直接呼び出してそれらを破棄します。

于 2013-05-22T23:30:11.963 に答える
2

他に方法はありませんが、デストラクタを明示的に呼び出すと、delete もメモリを解放しようとします。

配置 new で事前割り当てメモリを使用することは、コードではかなりまれです。典型的なユースケースは、固定メモリ アドレスの上にオブジェクトをマップしたい/必要があるときに、直接メモリ マップされたハードウェア インターフェイスを扱っている場合です。私は通常、コードの匂いを考えます。

特定のクラスのメモリ管理を微調整したい場合は、STL コンテナーをカスタム アロケーターと共に使用するか、その特定のクラスの new および delete 演算子をオーバーロードする方がはるかに優れています。

于 2013-05-22T23:29:44.130 に答える
0

はい、これが唯一の方法です。newを定義することは許されるが、許されないという点で非対称性がありdeleteます。[まあ、後者を行うことはできますがnew、例外がスローされたときにのみ呼び出されます (以下では適切に処理されません!)

テンプレートdestroyを使用して同じ結果を得ることができます。

class Test 
{
public:
    Test() {
        printf("In Constructor\n");
    }
    ~Test() {
        printf("In Destructor\n");
    }

    int val;
};

class Allocator
{
public:
    static void* allocate(size_t amount) { return std::malloc(amount);}
    static void unallocate(void* mem) { std::free(mem);}
    static Allocator allocator;
};

Allocator Allocator::allocator;

inline void* operator new(size_t size,  const Allocator& allocator)
{
    return allocator.allocate(size);
}


template<class T>
void destroy(const Allocator& allocator, T* object) 
{ 
    object->~T();
    allocator.unallocate(object);
}




int main()
{
    Test* t = new (Allocator::allocator) Test();

    destroy(Allocator::allocator, t);

    return 0;
}
于 2013-05-22T23:59:12.637 に答える