To the following code:
class C {
public:
static C& Instance() {
static C c;
return c;
}
~C(){std::cout << "c destructed\n";}
private:
C(){}
};
class D{//similar to C but prints `d destructed` on destruction
//...
int main()
{
auto c = C::Instance();
auto d = D::Instance();
}
//outputs (with gcc)
//d destructed
//c destructed
//d destructed
//c destructed
I have a couple of questions:
The point of this construct is to impose a construction order (and thus a destruction order).
Construction
Since these are local static variables, the order of construction is determined by the order in which their respective Instance
functions are called for the first time.
Since that is done in main
, the construction order is fully specified.
The only way to make the order unspecified is if you use them in static initialisation in different translation units, for instance if one has
C& the_c = C::Instance();
and the other has
D& the_d = D::Instance();
Destruction
The destruction of objects with static storage is the reverse of the order of construction.
3.6.3, Termination, paragraph 1:
If the completion of the constructor or dynamic initialization of an object with static storage duration is sequenced before that of another, the completion of the destructor of the second is sequenced before the initiation of the destructor of the first.
So the destruction order is fully specified by the construction order.
Note that this singleton construct is well specified even if one of them depends on the other, regardless of translation unit.
That is, this is perfectly safe, and it doesn't matter where it's defined:
class C {
public:
static C& Instance() {
static C c(D::Instance());
return c;
}
~C(){ m_d.doSomething(); } // Yes, this is safe.
private:
C(D& d) : m_d(d) { m_d.doSomething(); } // Yes, this is safe.
D& m_d;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With