views:

2888

answers:

8

I want to be able to initialize a vector of a size 'SIZE' before main. Normally I would do

static vector<int> myVector(4,100);

int main() {

    // Here I have a vector of size 4 with all the entries equal to 100

}

But the problem is that I would like to initialize the first item of the vector to be of a certain value, and the other to another value.

Is there an easy way to do this?

+14  A: 

Try this:

static int init[] = { 1, 2, 3 };
static vector<int> vi(init, init + sizeof init / sizeof init[ 0 ]);

Also, see std::generate (if you want to initialize within a function).

dirkgently
This is not only the most obvious way, but also the fastest and clearest way. +1 (at least if the other items are all zero)
Johannes Schaub - litb
no, this will give a 3 item vector (no extra elements), but for that, it's pretty neat.
Marcus Lindblom
+7  A: 

A bit hackish, but you could do this:

struct MyInitializer {
   MyInitializer() {
       myVector[0]=100;
       //...
   }
} myInitializer;  // This object gets constructed before main()
TrayMan
hackish, and a bit dangerous because you can't catch exceptions before main, but exactly what I do in these cases as well.
Nils Pipenbrinck
@Nils: Actually, the vector<T> class provides an iterator based ctor that can be coupled with arrays for just this sort of thing. Much safer, IMO.
dirkgently
+6  A: 

You can use Boost's comma-separated list.

Alex B
+7  A: 

Or just create a function and call that:

std::vector<int> init()
{
  ...
}

static std::vector<int> myvec = init()

A bit inefficient perhaps, but that might not matter to you now, and with C++0x and move it will be very fast.

Marcus Lindblom
A: 

Wrap it by a class:

class SpecialVector
{
  public:
    SpecialVector()
    {
      myVector[0] = 1;
      myVector[1] = 4;
      // etc.
    }
    const vector<int> & GetVector() const
    {
      return myVector;
    }
  private:
    vector<int> myVector;
 };
 static SpecialVector SpVec;

 int main() {
 }
Igor Oks
why why why.....
Yogesh Arora
global static is bad .... a-void them if you can! no way to catch exception, valgrind thinks it is a leak, hard to debug if there is an exception on application exit!
CodeMedic
+5  A: 

Here's alternative solution:

#include <vector>                  
static std::vector<int> myVector(4,100);

bool init()
{
    myVector[0] = 42;      
    return true;
}

bool initresult = init();

int main()                  
{
    ;
}
Pasi Savolainen
Interesting... Is it possible to somehow not waste the bool space?
Unknown
Yes, but not really. you could try embedding the initcall somewhere, but that would "hide" it: int somevalue = (init(), 42);
Pasi Savolainen
Also note that static is deprecated as a notifier for "internal" linkage (i.e. only within the translation unit). Use an anonymous namespace instead.
Marcus Lindblom
+5  A: 

C++0x will allow initializer lists for standard containers, just like aggregates:

std::vector<int> bottles_of_beer_on_the_wall = {100, 99, 98, 97};

Obviously not standard yet, but it's allegedly supported from GCC 4.4. I can't find documentation for it in MSVC, but Herb Sutter has been saying their c++0x support is ahead of the committee...

Steve Jessop
+2  A: 

Rather than use a global, I'd suggest it's better to use a local static. As the initialization of your vector takes place before main is entered any exceptions thrown there will not be caught by main. Say for example you have a type which when it's constructed may throw an exception:

class A {
public:
  A() { 
    // ... code that might throw an exception
  }
};

For the following initialization, the try/catch in the body of main will not catch the exception thrown by the constructor, and so your program will simply die immediately and you probably won't even be able to use a debugger to find the cause!

std::Vector<A> v(5, A());  // May throw an exception here not caught by main

int main () {
  try {
     // Exception for 'v' not handled here.
  }
  catch (...) {
  }
}

An alternative approach that will catch an exception from the constructor is to use a local static - which is initialized using the technique suggested by this answer.

std::Vector<A> init ();  // Returns a vector appropriately initialized

std::vector<A> & getV () {
  static std::vector<A> cache = init();
  return cache;
}

int main () {
  try {
     getV().at[0];    // First call to getV - so initialization occurs here!
  }
  catch (...) {
  }
}
Richard Corden