2

質問動的サイズの配列を作成するために「配置新規」を使用するにはどうすればよいですか?より具体的には、事前に割り当てられたメモリから配列要素にメモリを割り当てる方法。

私は次のコードを使用しています:

void* void_array = malloc(sizeof(Int)); 
Int* final_array = new(void_array) Int;

これにより、final_array *(配列ポインター)がvoid_array*によって予約されている場所から割り当てられることが保証されます。しかし、final_array要素はどうですか?事前に割り当てられたメモリからも割り当てられるようにしたい。

PS:タイルアーキテクチャを制御できるAPIを使用していると言わざるを得ません。mallocとまったく同じように機能する機能がありますが、割り当てられたメモリのプロパティを制御できるなど、他の機能もあります。したがって、基本的に行う必要があるのは、そのmallocのような関数を使用して、目的のプロパティ(たとえば、どのメモリバンクから、どこにキャッシュするかなど)でメモリを割り当てることです。

4

2 に答える 2

6

まず、メモリ割り当てとオブジェクト構築の分離について全員が同意していることを確認しましょう。それを念頭に置いて、オブジェクトの配列に十分なメモリがあると仮定しましょう。

void * mem = std::malloc(sizeof(Foo) * N);

現在、placement array-newは壊れているため、使用できません。正しいことは、各要素を個別に作成することです。

for (std::size_t i = 0; i != N; ++i)
{
    new (static_cast<Foo*>(mem) + i) Foo;
}

(キャストはポインター演算にのみ必要です。配置に必要な実際のポインター-newは単なるvoidポインターです。)

ちなみに、これはまさに標準ライブラリコンテナの動作方法であり、標準ライブラリアロケータの設計方法です。重要なのは、最初のメモリ割り当てで使用したため、要素の数をすでに知っているということです。したがって、C ++配列によって提供される魔法は必要ありませんnew。これは、配列サイズをどこかに格納し、コンストラクタとデストラクタを呼び出すことです。

破壊は逆に機能します:

for (std::size_t i = 0; i != N; ++i)
{
    (static_cast<Foo*>(mem) + i)->~Foo();
}

std::free(mem);

ただし、もう1つ知っておく必要があるのは、例外安全性です。上記のコードは、Fooスローしないコンストラクターがない限り、実際には正しくありません。正しくコーディングするには、アンワインドの場所も保存する必要があります。

std::size_t cur = 0;
try
{
    for (std::size_t i = 0; i != N; ++i, ++cur)
    {
        new (static_cast<Foo*>(mem) + i) Foo;
    }
}
catch (...)
{
    for (std::size_t i = 0; i != cur; ++i)
    {
        (static_cast<Foo*>(mem) + i)->~Foo();
    }
    throw;
}
于 2012-11-06T14:56:18.970 に答える
1

カスタムを使用する代わりに、malloc上書きoperator new()して使用する必要があります。これは演算子ではありませんnew; 実際に呼び出される関数がありますが、これは、オブジェクトを構築するための生のメモリを取得するためにoperator new()通常の(非配置)演算子によって使用される関数です。newもちろん、特別なメモリ管理が必要な場合にのみ上書きする必要があります。それ以外の場合、デフォルトバージョンは正常に機能します。

配列サイズが次のようになると仮定すると、使用方法は次のとおりですsize

Int* final_array = static_cast<Int*>(size == 0 ? 0 : operator new(sizeof(Int) * size));

次に、各要素を個別に構築および破棄できます。たとえば、要素の場合n

// Create
new(final_array + n) Int; // use whatever constructor you want

// Destroy
(final_array + n)->~Int();
于 2012-11-06T15:09:35.470 に答える