Reputation: 11
Hi i have a class tools which has static variable std::vector m_tools.
Can i insert the values into the static variable from Global scope of other classes defined in other files.
Example:
tools.h File
class Tools
{
public:
static std::vector<std::vector> m_tools;
void print()
{
for(int i=0 i< m_tools.size() ; i++)
std::cout<<"Tools initialized :"<< m_tools[i];
}
}
tools.cpp File
std::vector<std::vector> Tools::m_tools; //Definition
Using register class constructor for inserting the new string into static variable.
class Register
{
public:
Register(std::string str)
{
Tools::m_tools.pushback(str);
}
};
Different class which inserts the string to static variable in static variable
first_tool.cpp
//Global scope declare global register variable
Register a("first_tool");
////////
second_tool.cpp
//Global scope declare global register variable
Register a("second_tool");
Main.cpp
void main()
{
Tools abc;
abc.print();
}
Will this work?
In the above example on only one string is getting inserted in to the static list. Problem look like "in Global scope it tries to insert the element before the definition is done" Please let me know is there any way to set the static definiton priority? Or is there any alternative way of doing the same.
Upvotes: 1
Views: 956
Reputation: 116266
The initialization order of static global variables in different compilation units is not defined in C++ - this is why you have a problem.
A workaround may be to call a static function which contains the first static variable as local. This way you can force it to be initialized before it is used:
// tools.h
class Tools
{
public:
static std::vector<std::vector>& getTools();
...
};
// tools.cpp
std::vector<std::vector>& Tools::getTools() {
static std::vector<std::vector> tools;
return tools;
}
...
class Register
{
public:
Register(std::string str)
{
Tools::getTools().pushback(str);
}
};
Upvotes: 1
Reputation: 15180
The initialization of statics is not specified by C++. C++ FAQ Lite call it the "static initialization order fiasco"
my2c
Upvotes: 0
Reputation: 299810
You are likely, here, to encounter the issue referred to as Initialization Order Fiasco.
The problem is that the initialization order of globals (and static class variables are globals) is well-defined within a same translation unit (roughly, think .cpp) but is completely undefined across translation units. Therefore, there is no guarantee that the vector be initialized when you try to push items in there.
Your solution here ? Use local static variables:
class Tools
{
public:
static std::vector<std::string>& AccessTools()
{
static std::vector<std::string> Tools; // local static
return Tools;
}
private:
};
class Register
{
public:
Register(std::string str)
{
Tools::AccessTools().push_back(str);
}
};
It is guaranteed to be initialized upon first access... though it's not (and cannot be) thread safe; if you are in a multithreading situation, you need to call Tools::AccessTools
in main
before launching the other threads to guarantee the initialization.
Upvotes: 3