2011-11-02 10 views
5

C++でタイプに依存しないベクトルを作成しようとしていますが、これは2つの方法で区別されます。まず、ヒープ上のオブジェクトの実際の配列を維持するのではなく、少なくとも特定の点までオブジェクト自体のメモリを割り当てます。第2に、C++のコピー/アサインコンストラクタを使用することはできません。これはコードを遅くすると思われ、必要ではありません。C++オブジェクトインスタンスの移動/コピーについて

私は自分のコンピュータで管理しているコードベースを見ている間、LLVMのコードベースのクラスを見つけました。私が探しているものをほぼ完全に記述しています:SmallVector.h。 C++には比較的新しいので、なぜ設計上の決定が下されたのかが完全にはわかりません。たとえば、アレイがTではなくUという形で割り当てられているのはなぜですか?このコメントは手がかりを与えます:

Tにctorまたはdtorがある場合、自動的に実行されないようにするため、スペースを別のものとして表現する必要があります。 charの配列は素晴らしいですが、十分に整列されていない可能性があります。代わりに、スペースのためにいくつかのユニオンインスタンスを使用します。これは、最大限のアライメントを保証します。

Uは、当然のことながら、以下の組合を指し:

union U { 
    double D; 
    long double LD; 
    long long L; 
    void *P; 
} FirstEl; 

だから、私は推測し、ここに私の本当の質問は以下のとおりです。なぜTの配列を割り当てるんコンストラクタ/デストラクタが呼び出されることを意味するもの?これらのコンストラクタ/デストラクタを呼び出さずに、C++オブジェクトインスタンスをベクトルの内側と外側に移動する方法はありますか?私はちょうどLLVMのSmallVector実装を使用することができますが、私はそれを理解せずにコードを使用して嫌いです。

ベスト、 デュアン

+0

'C++のコンストラクタをコピー/代入すると、コードの速度が遅くなっているようです...' _correct_コードは必要なので、作成します。それらがmemcopiedされている場合はクラッシュするいくつかのクラスがあり、_not_にはデフォルトのコンストラクタがありません。 –

答えて

3

標準ライブラリアロケータの背後にある基本的な機械を見てください。多くの疑問があります。ここで

は、基本的な配分の原則です。我々は、メモリ割り当てとオブジェクト構築を分離します。大きな障害は、メモリがオブジェクトに対して正しく整列されなければならないことを、あなたが観察されるように、次のとおりです。

// getting memory 
void * p = malloc(1000); // version 1, system's allocator 
char q[1000];    // automatic array, this is also memory :-) 

// constructing an object 
T * m_x1 = ::new (p) T; // default-initialized 
T * m_x2 = ::new (q) T(); // value-initialized 
T * m_x3 = ::new (q + sizeof(T)) T(1, 'a'); // some specific constructor 

// destroying the objects: 
m_x1->~T(); 
m_x2->~T(); 
m_x3->~T(); 

あなたは心の中で、あなたは私が使用したchar配列qを取ると、それ一員作ることができたものを行うにはあなたのクラスの。つまり、クラスは常にオブジェクトを構築するためのメモリを持ち歩いています。

実際のオブジェクトの構築は、グローバルなplacement-new式で行われます。このように構築されたオブジェクトは、手動で破壊する必要があります(これはあなたの責任です)。

標準的なライブラリアロケータは、そのようなものです。

メモリ割り当てとオブジェクト構築を分離することは、あらゆる高度なメモリ管理、責任所有クラスの中心にあります。

オブジェクトが特定のアドレスに構築されると、の周りでメモリを移動してはいけません。オブジェクトはメモリ内の自分の位置に非常によく似ているかもしれません!オブジェクトを移動する有効な唯一の方法は、新しいオブジェクトをコピー/移動 - 構築することです。

1

はなぜTの配列を割り当てるんが、コンストラクタ/デストラクタが呼び出されることを意味するもの?

それは何の標準的な義務だからです。 Tの配列を割り当てることは、それぞれの要素を初期化することを意味します。 C++ 11では、charの配置制限が変更され、 "charの配列がうまく動作する"ようになりました。

これらのコンストラクタ/デストラクタを呼び出さずに、C++オブジェクトインスタンスをベクトルの前後に移動する方法はありますか?

はい、C++ 11の新機能である移動コンストラクタ/代入演算子を使用します。 ブーストでC++ 03とも移動支援をコンテナ用エミュレータライブラリがあります。

+1

注:_dynamically allocated_charの配列は、すべてのアラインメントに対して機能します。 charの自動配列はそうでないかもしれません。 –

0

C++ 11にも移動セマンティクスがあります。あなたのクラス(例えば、Foo)にムーブコンストラクタを実装すると、std :: vectorのパフォーマンスが大幅に向上します。

関連する問題