In C ++, does a "static initialization fiasco" only occur when accessing a data member of an object defined in another module?

Is the following example legal and safe C ++, or will it blow up depending on which customer decides to call the constructors of the global objects?

a.hpp:

class A {
public:
  A(int val_);
  int val;
};

extern A a;

      

a.cpp:

#include "a.hpp"

A::A(int val_) : val(val_) {}

A a(1234);

      

b.cpp:

#include <cassert>
#include "a.hpp"

class B {
public:
  B(A &a);
  int &ref;
};

B::B(A &a) : ref(a.val) {}

B b(a);

int main(int argc, char **argv) {
  assert(b.ref == 1234);
  assert(&b.ref == &a.val);
}

      

I need to do something like this in some real code I am writing (obviously my classes A and B are much more complex than this minimal example, but the data members they have to share are plain old int and bools) and I would rather use links than pointers.

+3


source to share


2 answers


Yes, this can blow up (according to the standard, anyway) because the constructor b

can work before a

and then ([class.cdtor] / p1) ...



For an object with a non-trivial constructor, referencing any non-static member or base class of the object before the constructor starts executing results in undefined.

+2


source


Your question is correct, but I think the module it is built a

in will be statically initialized correctly before the instance b

can access it, and this should be especially true if you build a

in another shared object and the class b

has an explicit, non-circular dependency from the class a

as in your example. This can also be easily tested on compilers / deployment platforms.

If you're still not convinced, you should force-initialize a

before b

with a free function a()

, as described here (Build on first use of the idiom):

Title:

A& a();

      



Compilation block:

A& a()
{
  static A _a;
  return _a;
}

      

Then you link _a

to a()

.

0


source







All Articles