Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Proper way to populate a static member list 2

Status
Not open for further replies.

titanandrews

Programmer
Feb 27, 2003
130
0
0
US
Hi All,

Can someone kindly tell me what is the proper way to initialize a static member list in C++? I have the following code:
Code:
#include <iostream>
#include <vector>

using namespace std;


class Foo
{
public:
    Foo();
    virtual ~Foo();

    static vector<int> ilist;    
    static void init_list();

};

inline Foo::Foo()
{
    Foo::init_list(); // This line gives a linker error.
}

inline Foo::~Foo()
{       
}

inline void Foo::init_list()
{
    Foo::ilist.push_back(100);
}

int main(int argc, char* argv)
{
    Foo foo;    
}

In the ctor I call the static method init_list, but that gives me a linker error. I am really not sure why. Can someone provide a clue?

Many thanks for your help!

-B
 
What's the error?
You don't need the Foo:: infront of init_list().
 
Since it is static, you will also need another declaration of Foo::ilist outside the class definition.
 
Hmmm... Not sure what either of you mean. Which Foo:: do I not need? I removed each one and it made no difference.

Why should I declare Foo::ilist again outside the class. Wouldn't that make 2 definitions, one as a class member and the other not??

Anyway... the linker error I get is "undefined reference to 'Foo::ilist'

I have tried your suggestions even though I don't understand them and they did not help. Any other ideas?

thanks,

B
 
You'll need both a declaration and a definition:

Code:
// foo.h

class Foo {
private:
    // This is a declaration; it reserves no space
    static int a_class_variable;
};

Code:
// foo.cpp
#include "foo.h"

// This is a definition; it reserves memory for the variable
int Foo::a_class_variable;

The [tt]Foo::[/tt] you don't need is the one in the [tt]init_list[/tt] code. You could have written it like this:
Code:
inline void Foo::init_list()
{
    ilist.push_back(100);
}
 
You may add direct definition of ilist member in this class definition file:
Code:
vector<int> Foo::ilist(1,100); // Use a proper vector ctor.
No need in init_list() member function (it's error prone approach to reinitialize static member on every Foo object allocation).
 
Well, this leads me back to my original question. What IS the proper way to initialize/populate a static member in C++? There are no static blocks in C++ like in Java, right? I don't want this data to get re-populated on every object instantiation. If someone could post a real compilable example of populating a static vector, I would really appreciate it.

thanks,

B
 
Code:
#include <iostream>
#include <vector>

using namespace std;


class Foo
{
public:
    Foo() { Foo::init_list(); }
    virtual ~Foo() { }

    static vector<int> ilist;    
    static void init_list();

};

inline void Foo::init_list()
{
    ilist.push_back(100);
}

vector<int> Foo::ilist;

int main()
{
    Foo foo;    
}
Code:
#include <iostream>
#include <vector>

using namespace std;


class Foo
{
public:
    virtual ~Foo() { }

    static vector<int> ilist;    
};

vector<int> Foo::ilist(1, 100);

int main()
{
    Foo foo;    
}
Code:
#include <iostream>
#include <vector>

using namespace std;


class Foo
{
public:
    virtual ~Foo() { }

    static vector<int> ilist;    
    static void init_list();

};

inline void Foo::init_list()
{
    ilist.push_back(100);
}

vector<int> Foo::ilist;

int main()
{
    Foo::init_list();
    Foo foo;    
}
All three of those have basically the same results.
 
Another way would be to add
Code:
static bool m_IsInitialized;
to the class definition.
Then change the init_list() function like this:
Code:
inline void Foo::init_list()
{
   if ( m_IsInitialized == false )
   {
      ilist.push_back(100);
      m_IsInitialized = true;
   }
}
Just make sure to set m_IsInitialized to false and declare it in the .cpp file...
 
To uolj:
All three of those have basically the same results?
Alas, #1: push 100 on every Foo allocation. So it has different semantics.

If you have essential dynamic population with non-trivial calculations, use cpjust's approach (but in this case you may use ilist.size() == 0 instead of a special boolean flag).

In all circumstances at first try to select a proper static member ctor. For example, std::vector class has v(n,data) ctor - etc.
 
ArkM said:
Alas, #1: push 100 on every Foo allocation. So it has different semantics.
Of course, that is a good point (although they actually do have the same results as posted since they are all complete programs).

cpjust's "approach" should really be considered an addition to the two approaches that use a special function for initializing the list. I would agree that checking for previous initialization would be appropriate for such an implementation. Whether you can do that with a special variable or by checking the state of the object to be initialized depends on the actual real-world situation.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top