0

Looks like I missed something fundamental here, but haven't worked it out.

Below is a snippet and its corresponding output.

What I wanted to do is: - Declare and initialize an array of structs, without knowing the number of elements in advance. - Ideally the array itself and its number of elements are private members.

What I tried:

  • Declared m_member_tab[] and m_num_members as private.
  • Created an Init() function that initializes m_member_tab[] and calculate m_num_members.

Outcome:

  • m_member_tab[] is initialized ok (see below output).
  • BUT inside the constructor (after calling Init), m_member_tab is corrupted.

    #include <iostream>
    using std::cout; using std::endl;
    
    class TArrayTest
    {
        public:
            TArrayTest();
    
        private:
            void Init();
    
            typedef struct _TMember
            {
                int m_key;
                int m_val;
            }
            TMember;
    
            TMember m_member_tab[];
            int m_num_members;
    };
    
    TArrayTest::TArrayTest()
    {
        Init();
        cout << "Ctor: Number of elements = " << m_num_members << endl;
        for( int i = 0; i < m_num_members; i++ )
        {
            cout << "Ctor: "
                << "key " << m_member_tab[i].m_key
                << " - val " << m_member_tab[i].m_val
                << endl;
        }
    };
    
    void TArrayTest::Init()
    {
        TMember m_member_tab[] =
        {
            { 1, 100 },
            { 2, 200 },
            { 3, 300 },
            { 4, 400 },
            { 5, 500 },
        };
        m_num_members = sizeof( m_member_tab ) / sizeof( TMember );
        cout << "Init: Number of elements = " << m_num_members << endl;
        for( int i = 0; i < m_num_members; i++ )
        {
            cout << "Init: "
                << "key " << m_member_tab[i].m_key
                << " - val " << m_member_tab[i].m_val
                << endl;
        }
    }
    
    int main()
    {
        TArrayTest test;
    }
    

Output:

    Init: Number of elements = 5
    Init: key 1 - val 100
    Init: key 2 - val 200
    Init: key 3 - val 300
    Init: key 4 - val 400
    Init: key 5 - val 500
    Ctor: Number of elements = 5
    Ctor: key 5 - val 32766
    Ctor: key 0 - val 0
    Ctor: key 0 - val 0
    Ctor: key -1212526907 - val 32623
    Ctor: key 0 - val 0
artm
  • 17,291
  • 6
  • 38
  • 54

3 Answers3

3

This member declaration:

    TMember m_member_tab[];

is not valid C++.

There is an additional problem in the init function, where you declare a local variable of the same name, but it doesn't matter: the above declaration is not just invalid, but since it's not at the end of the struct it doesn't even make sense as a language extension.

Instead, use std::vector, like this:

    std::vector<TMember> m_member_tab;

It keeps track of the array size, so you don't need that extra member.


In other news, C++ directly supports initialization of an instance of a class. You should not define ordinary function for that. Instead use the language mechanism for that, namely a constructor.

You can find information about constructors in any tutorial and any introductory C++ textbook.

The language supported mechanism has many advantages compared to an init function.


Oh, and seeing as each item in the array will contain a key and a value, do consider a std::map, or, if you can use C++11 and not just C++98/C03, std::unordered_map (faster but no sorted traversal of keys).

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

in the first line of void TArrayTest::Init():

TMember m_member_tab[] =
{
    { 1, 100 },
    { 2, 200 },
    { 3, 300 },
    { 4, 400 },
    { 5, 500 },
};

you declare "m_member_tab" a temporary variable, not Member variable. you should write like this: m_member_tab[] = { { 1, 100 }, { 2, 200 }, { 3, 300 }, { 4, 400 }, { 5, 500 }, };

wangli_64604
  • 103
  • 5
  • That alone doesn't help. But anyway +1 for pointing out my mistake of using reckless usage of temp var. – artm Jul 14 '15 at 10:21
1

The feature you are trying to use does not exist in C++ language. It is illegal to use [] in non-static member array declarations. It is allowed in static member array declarations, but non in non-static ones.

Even if your compiler somehow allows this declaration, it probably interprets it as a zero-sized array. The array size is fixed at that point - there's no way to somehow "intialize" it into a bigger array later.

Member array declaration with [] might be allowed by some compilers as a way to support C-style "struct hack". But that is a completely different technique.

Community
  • 1
  • 1
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Thanks. Looks like the only way (if I need to stick to C++98) is to declare a _public_ array of struct. Then in the implementation file (outside the class itself), I can initialize the array without knowing the number of items (following C99 syntax). That works, but what I don't really like is the fact the array itself (and the struct type) must be _public_. There is a suggestion above to use _vector_. But I haven't found a way to initialize vector of structs the way I did with C99 array (i.e., without knowing the number of elements). – artm Jul 14 '15 at 10:20
  • @artm: Um... I don't see how making the array public can make any difference here. As I said above, as long as your array remains a non-static member of the class, it is not possible to "redefine" the number of elements. – AnT stands with Russia Jul 14 '15 at 16:30