static object and member method called before cons

2019-08-18 09:00发布

问题:

I have two classes A and B such that A has a static B instance as its member. B has a function Show() and here is my class A:

class A
{
  A()
  {
    _b.Show();
  }
private:

  static B _b; 
};

and subsequent code is

A a;
B A::_b;

int main()
{
}

Now B::Show() called before B is constructed due to the sequence in which I have defined a and _b. But how does this work exactly i.e. how is it possible to make calls on an object that is still not constructed ?

回答1:

It's not possible, it's undefined behavior (in this case, because you're accessing an uninitialized object) because a is initialized before A::_b.

Look up static initialization order fiasco. You don't get an error because 99% of the times this happens, it's not easily diagnosable.



回答2:

This is the static initialisation order problem. Hard to solve in the general case, but one way to fix some cases is to put the dependency inside a function like this:

class A
{
public:
    A()
    {
        getB().Show();
    }
private:
    static B& getB()
    {
        static B b;
        return b;
    }
};

statics within functions are guaranteed to be initialised the first time that a call is made to it. Additionally in C++11 this is guaranteed to be thread safe as well.

Further reading:

http://www.parashift.com/c++-faq/static-init-order-on-first-use.html

Finding C++ static initialization order problems



回答3:

how is it possible to make calls on an object that is still not constructed?

Well, the simple answer is, exactly the way that code does it. <g>. Objects defined at file scope in the same translation unit are constructed in the order in which their definitions occur, so if the constructor of one object relies on another object, you have to ensure that the second object has already been constructed when the constructor for the first object runs.

C++ doesn't offer any help here; you have to keep track of it yourself.