Problem with initialize static std::vector<class> in same class constructor
How to correct declare static vector in class? Currently I have crash on one line because vector initialize too late.
Sample one:
#include "stdafx.h"
#include <vector>
class A{
private:
int aValue;
public:
static std::vector<A*> listOfA;
A(int i)
{
aValue = i;
A::listOfA.push_back(this); // !!! HERE crash in release mode only, in debug mode items add to vector, but remove when vector initialize
}
};
A testA(1);
std::vector<A*> A::listOfA;
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Sample two:
classA.h
#include <vector>
class A{
private:
int aValue;
public:
static std::vector<A*> listOfA;
A(int i);
};
classA.cpp
#include "stdafx.h"
#include "classA.h"
std::vector<A*> A::listOfA;
A::A(int i)
{
aValue = i;
A::listOfA.push_back(this); // !!! HERE crash in release mode only, in debug mode items add to vector, but remove when vector initialize
}
main.cpp
#include "stdafx.h"
#include "classA.h"
A testA(1);
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
In sample 2开发者_运维技巧 if cpp files in project have this order(compilation order) all works fine: classA.cpp main.cpp
If order this, we have crash: main.cpp classA.cpp
Statics are initialised in the order they appear in a file, so when you say:
A testA(1);
std::vector<A*> A::listOfA;
the first static is initialised, but its constructor tries to use the second static, with undefined results.
If the statics are in different files, the order of initialisation is unspecified, so it may appear to work if you are lucky Or unlucky). In general, don't write code that depends on the order of initialisation of statics.
quoted from: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14 There are many solutions to this problem, but a very simple and completely portable solution is to replace the global object listOfA, with a global function, listOfA(), that returns the object by reference.
std::vector<A*>& listOfA()
{
static std::vector<A*> ans;
return ans;
}
Since static local objects are constructed the first time control flows over their declaration (only), the above new listOfA() statement will only happen once: the first time listOfA() is called. Every subsequent call will return the same object. Then all you do is change your usages of listOfA to listOfA():
int _tmain(int argc, _TCHAR* argv[])
{
// do stuff
A::listOfA().dostuff();
// do stuff
}
This is called the Construct On First Use Idiom because it does just that: the global Fred object is constructed on its first use.
The downside of this approach is that the object is never destructed. There is another technique that answers this concern, but it needs to be used with care since it creates the possibility of another (equally nasty) problem.
[Edit] Sorry nbt, didn't see that you already linked to the faq. He deserves the credit[/Edit]
精彩评论