2012-04-26 11 views
2

std::vectorはどのようにオブジェクトを割り当てますか?それはちょうどstd::allocator::allocateを使ってメモリのブロックを作成するように思えますが、その後は決してstd::allocate::constructを呼び出しません。これは本当ですか? std::vectorはメモリだけを割り当て、メモリ割り当てとしてオブジェクトを構築しませんか?std :: vectorはどのようにオブジェクトを割り当てますか?

デフォルトのコンストラクタがない場合はどうなりますか?オブジェクトにデフォルトのコンストラクタがない場合、コンストラクタはどのように呼び出されますか?複数のパラメータがある場合はどうなりますか?

たとえば、このコードではデフォルトのコンストラクタはなく、std :: allocatorで許可されています。

#include <vector> 
using namespace std; 

class A{ 
protected: 
    int m; 
public: 
    explicit A(int a) : m(a) { } 
}; 

int main(){ 
    vector<A> test; 
    return 0; 
} 
+0

@Prætorian:この情報源を教えてください。私がちょうど質問に入れたコードは、VS2010でコンパイルすることを示しています。また、gccでコンパイルされると思います。 – chadb

+0

これはC++ 11標準から引用されています – Praetorian

+0

@Prætorian:これは新しいC++ 11ルールですか、それともC++ 03ですか? – chadb

答えて

8

これは、C++ 11以降に変更されています。

C++ 03では、constructは、インプレースでのコピー構築しか実行できませんでした。

ただし、特にstd::vectorはオブジェクトの配列ですが、サイズと容量が異なります。つまり、空の要素が、有用なデータを含む配列の部分の終わりを超えている可能性があります。

このため、標準ライブラリのアロケータには、「構築」と「メモリ割り当て」の分離があります。 allocatorは両方を行いますが、は同時にではありませんです。これにより、std::vectorは使用するメモリより多くのメモリを割り当てることができます。新しい要素を追加する場合、必ずしも多くのメモリを割り当てる必要はありません。 allocator::constructへの呼び出しを介して残っているスペアメモリを使用することができます。

また、std::vectorに要素を追加するすべてのC++ 03関数は、要素としてをパラメータとして取ります。 push_back,insert、さらにはsized constructor takes as a value as an argumentである。はい、デフォルトのパラメータですが、依然として要素として値を受け取ります。この要素は、コピーを取るアロケータのconstructメソッドへの呼び出しを使用して、をベクターにコピーしたです。

C++ 11では、allocator_traits<>::construct関数を使用するために標準コンテナが必要です。これは、そのパラメータを実際の構造に転送する可変関数です。この特性関数は(デフォルトでは特殊化することができます)、その呼び出しが整形式である場合はallocator::constructメソッドを呼び出します。そうでない場合は、newの配置を試みます。

これにより、新しいemplace関数が機能します。

しかし、標準ライブラリコンテナに含まれるオブジェクトは実際には構築されたオブジェクトです。アロケータのconstructメソッドが呼び出されない場合でも

0

それは実装依存だが、典型的な実装では、メモリのブロックを割り当てるstd::allocator::allocateを使用し、次いで構築する新たな配置を使用し、コピーコンストラクタを介して(またはC++ 11にコンストラクタを動かす)、インスタンス。

要素が消去されると、基本メモリが解放されていなくても、デストラクタが直接呼び出されてオブジェクトを破棄します。

+1

コンポーザーのコピーと移動は、新しいプレースメントとは関係ありません。 –

+0

デフォルトのコンストラクタがない場合はどうなりますか?オブジェクトにデフォルトのコンストラクタがない場合、コンストラクタはどのように呼び出されますか?複数のパラメータがある場合はどうなりますか? – chadb

+0

@ニコル:私は、 'std :: vector'は、建設オペレータの間にそのクラスのコピー(または移動)コンストラクタを使用する傾向があるということを指摘していました。新しいプレースメントはまだコンポジションを呼び出すので(非プレースメントnewのように)、それは私の意図である –

関連する問題