Initialization of an array of structs in C++

2019-06-11 02:31发布

问题:

If I have a struct like below:

typedef struct MyStruct {
    char **str;
    int num;    
} MyStruct;

Is there a way for me to initialize an array of this structures. Perhaps like below:

const MyStruct MY_STRUCTS[] = {
    {
        {"Hello"}, 
        1
    },
    {
        {"my other string"}, 
        3
    },
};

Ultimately I would like to have a constantly declared array of structs inside a C++ class. How can this be done? Is it possible to have a privately declared member that is pre-initialized?

回答1:

Sure, you'd write it like this:

#include <string>
#include <vector>

struct MYStruct
{
     std::vector<std::string> str;
     int num;
};

MyStruct const data[] = { { { "Hello", "World" }, 1 }
                        , { { "my other string" }, 3 }
                        };

Unless I'm misunderstanding and you actually just want num to count the number of elements. Then you should just have:

std::vector<std::string> data[] = { { "Hello" }
                                  , { "my", "other", "string" }
                                  };

And you can recover the element sizes with data[0].size(), data[1].size(), etc.


If everything is determined statically and you just want a compact reference, you still need to provide storage, but everything is virtually the same as in C:

namespace    // internal linkage
{
    char const * a0[] = { "Hello" };
    char const * a1[] = { "my", "other", "string" };
    // ...
}

struct Foo
{
    char const ** data;
    std::size_t len;
};

Foo foo[] = { { a0, 1 }, { a1, 3 } };

Since the size is std::distance(std::begin(a0), std::end(a0)), you could simplify the last part with a macro that just takes a0 as an argument. And instead of handwriting Foo, you might just use std::pair<char const **, std::size_t>.



回答2:

You mean something like this:

// In some headerfile:

class X
{
  private:
    static const MyStruct MY_STRUCTS[]; 
};

// in some .cpp file:

const X::MyStruct MY_STRUCTS[] = { { {"Hello"}, 1}, { "Other String"} , 3 } }; 

That assumes, however, that you have a char *str;, since char **str; requires a secondary variable to take the address off. Or, you could use std::vector<string>, and that would solve the problem.



回答3:

You can use something like

class foo {
    MyStruct array[2];
public:
    foo()
        : array{ { "a", 1 }, { "b", 2 }}
    {
    }
};

assuming you struct's first member is actually char const* rather than char** as you initialization example suggests.