Подтвердить что ты не робот

Как инициализировать stl-вектор объектов, которые сами имеют нетривиальные конструкторы?

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

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

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

4b9b3361

Ответ 1

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

Используйте конструктор 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));
        }
    }
};

Другой вариант - это список инициализации конструктора, если параметр С++ 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.

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

Ответ 2

Если элементы вектора не являются конструктивными по умолчанию, то есть определенные вещи, которые вы не можете сделать с вектором. Вы не можете написать это (пример 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.

Ответ 3

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

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

Ответ 4

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