2009-06-17 17 views
3

ベクトルテンプレートが2つの割り当てを実行するのはなぜかというと、1つだけが であると思われていたのです。STLベクトル割り当て

#include <vector> 
#include <iostream> 

class A { 
    public: 
     A(const A &a) { 
      std::cout << "Calling copy constructor " << this << " " << &a << "\n"; 
     } 
     A() { 
      std::cout << "Calling default constructor " << this << "\n"; 
     } 
     ~A() { 
      std::cout << "Calling destructor " << this << "\n"; 
     } 
}; 

int main(int argc, char **argv) 
{ 
    std::vector <A> Avec; 

    std::cout << "resize start\n"; 
    Avec.resize(1); 
    std::cout << "resize end\n"; 

    return 0; 
} 

出力:例:このため

 
resize start 
Calling default constructor 0x7fff9a34191f 
Calling copy constructor 0x1569010 0x7fff9a34191f 
Calling destructor 0x7fff9a34191f 
resize end 

答えて

15

それは、その後、リサイズに渡すためにデフォルトコンストラクタでオブジェクトを作成して、2つの割り当てを行っていませんそのオブジェクトを新しい位置にコピーした後、引数を破棄します。

あなたはサイズを変更するために、引数を見れば:タイプTの

void resize(n, t = T()) 

それは債務不履行引数としてデフォルトを構築しているオブジェクト(これはあなたの出力に呼び出されるデフォルトのコンストラクタです)。次に、関数内で、これを正しい位置にコピーします(これはコピーコンストラクターです)。 resize関数が終了すると、引数(出力のデストラクタ呼び出し)が破棄されます。ここで

0

あなたはベクトルテンプレートは、コピーを作成することにより、オブジェクトを作成する方法オブジェクトを初期化した場合。 あなたが作るべきコピーコンストラクタを呼び出すにしたくない場合は、次の

vector<A*> Avec; 
avec.push_back(new A()); 

http://www.cplusplus.com/reference/stl/vector/vector/

+0

私は思います - 新しいA()の1つ - push_back()のコピーのための1つ – ynimous

+0

@ynimous:実際はそうではありませんが、上記のコードはセマンティクスを変更して、ベクトルにポインタが含まれるようにします。これはポインタを作成してコピーする(これはおそらくより速い)一方、A要素を1回だけ作成します。 –

+1

このアプローチの問題は、コードのセマンティクスを変更していることです。オブジェクトがベクトル内で値で保持される前に、ベクトルの破壊はすべての含まれた要素の破壊を暗示しました。要素がポインタを介して保持されるので、コードは適合されなければならず、ユーザーはすべてのリソース(Aオブジェクト)を手動で破棄する必要があります。 A構造の数を減らしたが、コードはより壊れやすくなり、リソースリークが発生しやすくなった。 –

0

は推測です:

  1. コンパイラAvecの初期割り当てを再注文
  2. 「スタートのサイズを変更する」ベクターは、最初は0要素
  3. に割り振られた後でサイズ変更が取得するまでデフォルトのA(デフォルトのAを作成し、それをベクターにコピーして一時的に削除することによって達成された)の新しい要素があります。