2013-04-10 27 views
5

私はC++を学んでおり、私はSTLのコンテナを見てきました。私はたくさんの質問をしていますが、これが最初にできると思います。このクラスとそのベクトルを考えてみましょう。ベクトル初期化の構造とコピーはなぜですか?

class A { 
    int i; 
    // A(const A&); 
public: 

    A(int i) : i(i) {cout << "consting " << i << endl;} 
    A(const A& ot) : i(ot.i) {cout << "copying " << i << endl;} 

}; 

int main() { 
    vector<A> v1 = {A(1),A(2),A(3),A(4)}; 
    vector<A> v2(1,A(5)); 
    vector<A> v3; 
    v3.push_back(A(6)); 
} 

は明らかにそれが構築し、各Aをコピーしている私に出力

consting 1 
consting 2 
consting 3 
consting 4 
copying 1 
copying 2 
copying 3 
copying 4 
consting 5 
copying 5 
consting 6 
copying 6 

を与えます。

これを防止する方法はありますか?つまり、余分なコピーを避けて、ベクターにAを組み立てるだけです。これは可能ですか?なぜ誰かが理由を説明できないのですか?ありがとうございました。

EDIT:ちょうど完了のためpush_backため が同じ

+3

問題は 'のstd :: initializer_list'は、それが要素をコピーする必要があります使用してそのすべてのコンストラクタ内容だ「所有する」ということです。それは理にかなっていませんが、 'std :: initializer_list'がどのように動作するかです。不運。 – ipc

+0

@ipc他の建設事例はどうですか?それは他の人にとって可能ですか? –

+0

@Aurora:実際、あなたが考えるよりもはるかに簡単です。 'A(6)'を追加する代わりに '6'を追加するだけです。 –

答えて

3

を行います。このような初期化リストコンストラクタを使用する場合にコピーを避けることはできません。代替は最初に適切な容量を確保してからemplace_backの各オブジェクトすることです:

vector<A> v1; 
v1.reserve(4); 
v1.emplace_back(1); 
v1.emplace_back(2); 
v1.emplace_back(3); 
v1.emplace_back(4); 

As you can see、これが唯一の次の出力が生成されます。

consting 1 
consting 2 
consting 3 
consting 4 
+0

'emplace_back'はC++ 11でのみ利用できますか? –

+3

@Auroraそうですが、使用している初期化子リストコンストラクタもそうです。 –

+0

@Aurora:正しい。同じことが、コードで使用していると思われるリストを初期化する場合にも当てはまります。 –

4

残念ながらリストの初期化はstd::vectorとのコピーが必要です。あなたのコンテナが固定サイズで、一つの代替ではなくstd::arrayを使用することであることがわかっている場合:

std::array<A, 4> a1 = {{A(1),A(2),A(3),A(4)}}; 

stdout: 
consting 1 
consting 2 
consting 3 
consting 4 
+0

+1良い提案。 –

関連する問題