0

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 ?

Arun
  • 3,138
  • 4
  • 30
  • 41

3 Answers3

4

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.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • hmmm.. But how does it work ? Though erroneously, but still how a call like that is possible ? Could you shed light on the low level details as to why it works ? – Arun Oct 04 '12 at 10:13
  • @Arun technically, UB means anything can happen. In practice, if `_b.Show();` doesn't access memory of `_b` (the call is resolved statically) it won't crash. Probably won't crash even if it did, because the memory is there, albeit un-initialized. – Luchian Grigore Oct 04 '12 at 10:16
  • 2
    Um, no, it's not the so-called "static initialization order fiasco"; that refers to the unspecified order of initialization of static objects defined in **different** translation units. The order of initialization in this code is well defined, and the problem is simply that the definitions are written in the wrong order. – Pete Becker Oct 04 '12 at 11:15
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

Community
  • 1
  • 1
0

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165