Ниже приведен отрывок из книги Бьярна Страуструпа «Язык программирования C ++»:
Нет гарантий, независимых от реализации, о порядке построения нелокальных объектов в разных единицах компиляции. Например:
// file1.c:
Table tbl1;
// file2.c:
Table tbl2;
Будет ли tbl1 построен до tbl2 или наоборот, зависит от реализации. Порядок не гарантируется даже в каждой конкретной реализации. Динамическое связывание или даже небольшое изменение в процессе компиляции может изменить последовательность. Порядок уничтожения аналогичным образом зависит от реализации.
Программист может обеспечить правильную инициализацию, реализуя стратегию, которую реализации обычно используют для локальных статических объектов: переключение в первый раз. Например:
class Zlib {
static bool initialized;
static void initialize() { /* initialize */ initialized = true; }
public:
// no constructor
void f()
{
if (initialized == false) initialize();
// ...
}
// ...
};
Если существует много функций, требующих проверки первого переключателя, это может быть утомительным, но часто управляемым. Этот метод основан на том факте, что статически размещенные объекты без конструкторов инициализируются в 0 . Действительно сложный случай - это тот случай, когда первая операция может быть критичной по времени, поэтому накладные расходы на тестирование и возможную инициализацию могут быть серьезными. В этом случае требуется дополнительная хитрость (§21.5.2).
Альтернативный подход для простого объекта - представить его как функцию (§9.4.1):
int& obj() { static int x = 0; return x; } // initialized upon first use
Новые переключатели не справляются со всеми возможными ситуациями. Например, можно создавать объекты, которые ссылаются друг на друга во время строительства. Таких примеров лучше избегать. Если такие объекты необходимы, они должны быть тщательно построены поэтапно.