How do I initialize a stl vector of objects who themselves have non-trivial constructors?

Rafael S. Calsaverini picture Rafael S. Calsaverini · May 26, 2011 · Viewed 61.2k times · Source

suppose I have the following class:

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

And suppose this class don't have a default trivial constructor MyInteger(). I must always supply an int to initialize it for some reason. And then suppose that somewhere in my code I need a vector<MyInteger>. How do I initialize each MyInteger component in this vector<>?

I have two situations (probably the solution is the same, but I'll state them anyway), a normal variable inside a function:

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

and as data in a class:

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?
};

Is it possible to do it just in the initialization list or must I write the initialization by hand in the MyFunClass(int, int) constructor?

This seems so very basic, and yet I somehow missed it inmy book and can't find in the web.

Answer

user405725 picture user405725 · May 26, 2011

There are many ways to get there. Here are some of them (in no particular order of presence).

Use vector(size_type n, const T& t) constructor. It initializes vector with n copies of t. For example:

#include <vector>

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

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

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

Push elements into vector one by one. This might be useful when values should be different. For example:

#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));
        }
    }
};

Another option is constructor initialization list, if C++0x is an option:

#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) /* ... */})
    {
    }
};

Of course, there is an option to provide default constructor and/or use something other than std::vector.

Hope it helps.