Здравствуйте, vdimas, Вы писали:
К>>Если один объект из своего конструктора или из инициализирующей функции создал другой статический объект, тот добавится вперёд него
V>Сам добавиться?
Ну как сам.
Рядом с каждым статическим объектом есть две незримых функции — первая его инициализирует и добавляет в atexit вторую, а вторая разрушает.
Если очень грубо, то
// static X x (a,b,c);
using X_Data = aligned_storage<sizeof(X), alignof(X)>::type;
static X_Data x_data;
static bool x_created = false;
static X& x = (X&)x_data;
void touch_x() {
if (!x_created) { // сейчас не будем морочить себе голову вопросами реентера и многопоточности
new (&x) X(a,b,c);
atexit(kill_x);
x_created = true;
}
}
void kill_x() {
if (x_created)
x.~X();
}
X& take_x() { touch_x(); return x; }
//////// зависимый от него static Y y(x);
void touch_y() {
if (!y_created) {
new (&y) Y(take_x()); // в рамках take_x -> touch_x мы добавим kill_x
atexit(kill_y); // вперёд добавления kill_y
y_created = true;
}
}
Для локальных объектов (синглетоны Мейерса) всё это добро существует физически.
Для нелокальных — если компилятор предпочитает пакетную инициализацию всех переменных в единице трансляции, то он может сократить слагаемые — родить две такие функции touch_everything, kill_everything на всю единицу.