Как компилятор разрешает бесконечные циклы ссылок?
// edited by Neil Butterworth to conserve vertical space
#include <stdio.h>
struct A;
struct B;
A& GetAInstance();
B& GetBInstance();
struct A {
A() {
printf( "A\n" );
}
~A() {
printf( "~A\n" );
B& b = GetBInstance();
}
};
struct B {
B() {
printf( "B\n" );
}
~B() {
printf( "~B\n" );
A& a = GetAInstance();
}
};
A& GetAInstance() {
static A a;
return a;
}
B& GetBInstance() {
static B b;
return b;
}
int main( ) {
A a;
}
Рассмотрим приведенный выше сценарий. Я ожидаю, что это приведет к бесконечному эталонному циклу, в результате чего программа не сможет выйти из статической деинициализации, но программа отлично справилась со следующей распечаткой:
A
~A
B
~B
A
~A
Это было неожиданно.
Как компилятор справляется с этой ситуацией? Какие алгоритмы он использует для решения бесконечной рекурсии? Или я неправильно понял что-то фундаментальное? Это где-то в стандарте, определяемом как undefined?
Ответы
Ответ 1
Компилятор эффективно сохраняет bool
с каждым static
, чтобы запомнить, был ли он инициализирован.
Это порядок:
Внутри main:
Очистка статики:
- Уничтожить
static B
-
- Построить
static A
- Уничтожить
static A
3.6.3/1 в стандарте указывает, что он должен работать таким образом, даже когда a static
создается при очистке, как в этом случае.
Ответ 2
Это поведение, вероятно, вызвано тем, что вы используете статические экземпляры. Компилятор наверняка заботится о статусе статических переменных, чтобы избежать выполнения нескольких инициализаций/деинициализаций.