views:

118

answers:

3

Hi! I wonder if there is the "nicer" way of initialising a static vector than below?

class Foo
{
    static std::vector<int> MyVector;
    Foo()
    {
        if (MyVector.empty())
        {
            MyVector.push_back(4);
            MyVector.push_back(17);
            MyVector.push_back(20);
        }
    }
}

It's an example code :)

The values in push_back() are declared independly; not in array or something.

Edit: if it isn't possible, tell me that also :)

+4  A: 

Typically, I have a class for constructing containers that I use (like this one from boost), such that you can do:

const list<int> primes = list_of(2)(3)(5)(7)(11);

That way, you can make the static const as well, to avoid accidental modifications.

For a static, you could define this in the .cc file:

// Foo.h

class Foo {
  static const vector<int> something;
}

// Foo.cc

const vector<int> Foo::something = list_of(3)(5);

In C++Ox, we'll have a language mechanism to do this, using initializer lists, so you could just do:

const vector<int> primes({2, 3, 5, 7, 11});

See here.

Todd Gardner
I guess if he emphasises that the values are "not in an array", then the new feature won't do much good either. I guess there's no way around either getting them into some sort of collection or live with the repeated insertion calls.
Alexander Rautenberg
I think list_of is what I need. It looks simple and, I think, faster than multiple push_backs. When I said "they are not in array", I didn't mention that they can't be in one.
Xirdus
Most likely, it is internally using multiple push_back()s, so it isn't "faster" in that sense. It does avoid a conditional in the constructor, which would make that faster. However, static initialization is probably not where your code spends majority of time, so optimizing those sections will most likely not be a noticeable gain gain.
Todd Gardner
A: 

You could try this one:

int arr[] = { 1,2,3,4,5,6,7,8,9 };
MyVector.insert(MyVector.begin(), arr, &arr[sizeof(arr)/ sizeof(*arr)]);

But it's probably only worth when you have a really long vector, and it doesn't look much nicer, either. However, you get rid of the repeated push_back() calls. Of course, if your values are "not in an array" you'd have to put them into there first, but you'd be able to do that statically (or at least references/pointers), depending on the context.

Alexander Rautenberg
+3  A: 

In C++03, the easiest way is to use a factory function:

std::vector<int> MakeVector()
{
    std::vector v;
    v.push_back(4);
    v.push_back(17);
    v.push_back(20);
    return v;
}

std::vector Foo::MyVector = MakeVector(); // can be const if you like

"Return value optimisation" should mean that the array is filled in place, and not copied, if that is a concern. Alternatively, you could initialise from an array:

int a[] = {4,17,20};
std::vector Foo::MyVector(a, a + (sizeof a / sizeof a[0]));

If you don't mind using a non-standard library, you can use Boost.Assignment:

#include <boost/assign/list_of.hpp>

std::vector Foo::MyVector = boost::list_of(4,17,20);

In C++0x, you can use the uniform initialisation syntax:

std::vector Foo::MyVector = {4,17,20};
Mike Seymour
+1 for new language features (uniform initialization syntax ftw).
rubenvb
This function is bad idea because there will be only one static vector to fill.
Xirdus
@Xirdus: What makes it a bad idea? If you need to initialise a non-empty array, then that's one way to do it.
Mike Seymour
I asked for something what will shorten and clear the code. The above code (in my certain case) is as useful as #define MyMain main(int argc, char** argv)
Xirdus
@Xirdus: No, you asked for a "nicer" way to initialise a vector. My answer gives a way of actually initialising it (rather than populating an array that was initialised empty), which allows you (for example) to initialise a constant vector. So it does answer what you asked, if not what you thought you meant.
Mike Seymour