Как инициализировать вектор stl объектов, которые сами имеют нетривиальные конструкторы? - PullRequest
30 голосов
/ 26 мая 2011

предположим, у меня есть следующий класс:

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

И предположим, что у этого класса нет тривиального конструктора по умолчанию MyInteger(). Я всегда должен предоставить int для его инициализации по какой-то причине. А потом предположим, что где-то в моем коде мне нужна vector<MyInteger>. Как мне инициализировать каждый MyInteger компонент в этом vector<>?

У меня есть две ситуации (возможно, решение одно и то же, но я все равно их изложу), обычная переменная внутри функции:

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)?

Это кажется очень простым, и все же я почему-то пропустил это в моей книге и не могу найти в Интернете.

Ответы [ 5 ]

30 голосов
/ 26 мая 2011

Есть много способов добраться туда. Вот некоторые из них (без определенного порядка присутствия).

Используйте vector(size_type n, const T& t) конструктор. Он инициализирует вектор с n копиями t. Например:

#include <vector>

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

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

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

Вставить элементы в вектор один за другим. Это может быть полезно, когда значения должны отличаться. Например:

#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.

Надеюсь, это поможет.

10 голосов
/ 26 мая 2011

Если элементы вектора не являются конструируемыми по умолчанию, то есть некоторые вещи, которые вы не можете сделать с вектором.Вы не можете написать это (пример 1):

vector<MyInteger> foo(10);

Вы можете, однако, написать это (пример 2):

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

(для этого требуется только конструктор копирования.) ВторойАргумент является инициализатором для элементов вектора.

В вашем случае вы также можете написать:

vector<MyInteger> foo(10, 37);

..., поскольку MyInteger имеет неявный конструктор, принимающий "int"в качестве аргумента.Таким образом, компилятор приведёт 37 к MyInteger (37) и выдаст тот же результат, что и в примере 2.

Возможно, вы захотите изучить документацию по std :: vector .

6 голосов
/ 26 мая 2011

Помимо всех ответов, которые очень хорошо ответили на вопрос, в случае, если ваш класс MyInteger не копируемый, вы можете использовать этот трюк: вместо создания vector< MyInteger> вы можете создать vector< shared_ptr< MyInteger > >

6 голосов
/ 26 мая 2011
vector<MyInteger> foo(10, MyInteger(MY_INT_VALUE));

MyFunClass(int size, int myIntegerValue) : myVector(size, MyInteger(myIntegerValue)) {}; 
1 голос
/ 15 июля 2018

Списки инициализации могут использоваться без ссылки на базовые объекты.

#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 два

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...