How to initialize static vector member?

2020-07-10 11:46发布

For example

struct A
{
    static vector<int> s;
};

vector<int> A::s = {1, 2, 3};

However, my compiler doesn't support initialization list. Any way to implement it easily? Does lambda function help here?

5条回答
干净又极端
2楼-- · 2020-07-10 12:13

You can initialize an std::vector from two pointers

int xv[] = {1,2,3,4,5,6,7,8,9};
std::vector<int> x(xv, xv+(sizeof(xv)/sizeof(xv[0])));

You can even factor this out in a template function:

template<typename T, int n>
std::vector<T> from_array(T (&v)[n]) {
    return std::vector<T>(v, v+n);
}
查看更多
beautiful°
3楼-- · 2020-07-10 12:19

Another idea:

struct A
{
  static std::vector<int> s;
};

std::vector<int> A::s;

static bool dummy((A::s.push_back(1), A::s.push_back(2), A::s.push_back(3), false));
查看更多
Juvenile、少年°
4楼-- · 2020-07-10 12:20

Write a simple init function for the vector:

vector<int> init()
{
  vector<int> v;
  v.reserve(3);
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  return v;
};

vector<int> A::s = init();
查看更多
啃猪蹄的小仙女
5楼-- · 2020-07-10 12:26

Any way to implement it easily?

There's nothing particularly elegant. You can either copy the data from a static array, or initialise it with the result of a function call. The former might use more memory than you'd like, and the latter needs some slightly messy code.

Boost has a library to make that slightly less ugly:

#include <boost/assign/list_of.hpp>
vector<int> A::s = boost::assign::list_of(1)(2)(3);

Does lambda function help here?

Yes, it can save you from having to name a function just to initialise the vector:

vector<int> A::s = [] {
    vector<int> v;
    v.push_back(1);
    v.push_back(2); 
    v.push_back(3);
    return v;
}();

(Strictly speaking, this should have an explicit return type, []()->vector<int>, since the lambda body contains more than just a return statement. Some compilers will accept my version, and I believe it will become standard in 2014.)

查看更多
Deceive 欺骗
6楼-- · 2020-07-10 12:34

I always fear being shot down for initialization ordering here for questions like this, but..

#include <iostream>
#include <vector>
#include <iterator>

struct A
{
    static std::vector<int> s;
};

static const int s_data[] = { 1,2,3 };
std::vector<int> A::s(std::begin(s_data), std::end(s_data));

int main()
{
    std::copy(A::s.begin(), A::s.end(), 
              std::ostream_iterator<int>(std::cout, " "));
    return 0;
}

Output

1 2 3

Just because you can doesn't mean you should =P

Winning the award for the least efficient way to do this:

#include <iostream>
#include <vector>
#include <cstdlib>
using namespace std;

template<typename T>
std::vector<T> v_init(const T& t)
{
    return std::vector<T>(1,t);
}

template<typename T, typename... Args>
std::vector<T> v_init(T&& t, Args&&... args)
{
    const T values[] = { t, args... };
    std::vector<T> v1(std::begin(values), std::end(values));
    return v1;
}

struct A
{
    static std::vector<int> s;
};

std::vector<int> A::s(v_init(1,2,3,4,5));


int main(int argc, const char *argv[])
{
    std::copy(A::s.begin(), A::s.end(), std::ostream_iterator<int>(std::cout, " "));
    return 0;
}

Output

1 2 3 4 5 

This should puke at compile-time if T and anything in Args... is not type-compliant or type-castable. Of course, if you have variadic templates odds are you also have initializer lists, but it makes for fun brain-food if nothing else.

查看更多
登录 后发表回答