Search code examples
c++constructorinitializationinitialization-list

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


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.


Solution

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