web-dev-qa-db-ja.com

それ自体が重要なコンストラクタを持つオブジェクトのstlベクトルを初期化するにはどうすればよいですか?

次のクラスがあると仮定します。

_class MyInteger {
private:
  int n_;
public:
  MyInteger(int n) : n_(n) {};
  // MORE STUFF
};
_

そして、このクラスにデフォルトの単純なコンストラクタMyInteger()がないと仮定します。何らかの理由でそれを初期化するには、常にintを提供する必要があります。そして、私のコードのどこかに_vector<MyInteger>_が必要だとします。この_vector<>_の各MyIntegerコンポーネントを初期化するにはどうすればよいですか?

私は2つの状況があります(おそらく解決策は同じですが、とにかくそれらを述べます)、関数内の通常の変数:

_int main(){
    vector<MyInteger> foo(10);  //how do I initialize each 
                                //MyInteger field of this vector? 
    doStuff(foo);
}
_

クラス内のデータとして:

_class MyFunClass {
private:
   vector<MyInteger> myVector;

public:
   MyFunClass(int size, int myIntegerValue) : myVector(size) {}; 
   // what do I put here if I need the 
   // initialization to call MyInteger(myIntegerValue) for all 
   // components of myVector?
};
_

初期化リストだけでそれを行うことは可能ですか、またはMyFunClass(int、int)コンストラクターで手動で初期化を記述する必要がありますか?

これは非常に基本的なように思えますが、それでも私の本で見逃してしまい、ウェブで見つけることができません。

31

そこに到達する多くの方法があります。それらのいくつかを以下に示します(特定の順序ではありません)。

vector(size_type n, const T& t)コンストラクターを使用します。 ntコピーでベクターを初期化します。例えば:

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values (10, MyInt (20))
    {
    }
};

要素を1つずつベクトルにプッシュします。これは、値が異なる必要がある場合に役立ちます。例えば:

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values ()
    {
        values.reserve (10); // Reserve memory not to allocate it 10 times...
        for (int i = 0; i < 10; ++i)
        {
            values.Push_back (MyInt (i));
        }
    }
};

C++ 0xがオプションの場合、別のオプションはコンストラクター初期化リストです。

#include <vector>

struct MyInt
{
    int value;
    MyInt (int value) : value (value) {}
};

struct MyStuff
{
    std::vector<MyInt> values;

    MyStuff () : values ({ MyInt (1), MyInt (2), MyInt (3) /* ... */})
    {
    }
};

もちろん、デフォルトのコンストラクタを提供したり、std::vector以外の何かを使用したりするオプションがあります。

それが役に立てば幸い。

30
user405725

ベクターの要素がデフォルトで構築できない場合、ベクターでできないことがいくつかあります。これを書くことはできません(例1):

vector<MyInteger> foo(10);

ただし、これを書くことができます(例2):

vector<MyInteger> foo(10, MyInteger(37));

(これには、コピーコンストラクタのみが必要です。)2番目の引数は、ベクトルの要素の初期化子です。

あなたの場合、次のように書くこともできます:

vector<MyInteger> foo(10, 37);

... MyIntegerには引数として「int」をとる非明示的なコンストラクターがあるためです。したがって、コンパイラーは37をMyInteger(37)にキャストし、例2と同じ結果を返します。

std :: vectorのドキュメント を調べてください。

11
Nemo

質問に非常によく答えたすべての回答に加えて、クラスMyIntegerがコピー構築可能でない場合、このトリックを使用できます。vector< MyInteger>を作成する代わりに、vector< shared_ptr< MyInteger > >を作成できます

6
BЈовић
vector<MyInteger> foo(10, MyInteger(MY_INT_VALUE));

MyFunClass(int size, int myIntegerValue) : myVector(size, MyInteger(myIntegerValue)) {}; 
6
mbykov

初期化リストは、基礎となるオブジェクトを参照せずに使用できます。

#include <string>
#include <vector>
using namespace std;


class Test
{
   public:
   struct NumStr
   {
      int num;
      string str;
   };

   Test(vector<int> v1,vector<NumStr> v2) : _v1(v1),_v2(v2) {}
   vector<int> _v1;
   vector<NumStr> _v2;
};

int main()
{
   Test t={ {1,2,3}, {{1,"one"}, {2,"two"}, {3,"three"}} };
   cout << t._v1[1] << " " << t._v2[1].num << " " << t._v2[1].str << endl;
   return 0;
}

出力:2 2 2

1
edW