Разве у компилятора нет всей информации, необходимой ему для генерации дерева зависимостей всех глобальных переменных и создания для них четко определенного и правильного порядка инициализации? Я понимаю, что вы можете написать циклическую зависимость с глобальными переменными — сделать только тот случай неопределенного поведения — и компилятор может предупредить и, возможно, сообщить об ошибке.
Обычно причиной такого рода вещей является то, что это будет обременительно для производителей компиляторов или приведет к значительному замедлению компиляции. У меня нет метрик или доказательств, которые бы указывали на то, что ни одно из них не было бы правдой в этом случае, но я склоняюсь к тому, что ни один из них не будет правдой
Хм, представьте следующую настройку, которая является совершенно допустимой в C ++, но сложно проанализировать:
// TU #1
bool c = coin();
// TU #2
extern bool c;
extern int b;
int a = c ? b : 10;
// TU #3
extern bool c;
extern int a;
int b = c ? 20 : a;
Понятно, что сначала нужно инициализировать TU # 1, но что потом? Стандартное решение со ссылками на статику позволяет вам правильно писать этот код со стандартным C ++, но решение этого вопроса путем исправления глобального порядка инициализации кажется сложным.
Часть компилятор может иметь дело с фактически определенным: объекты со статической длительностью хранения строятся в порядке их определения в единице перевода. Порядок уничтожения только обратный.
Когда дело доходит до упорядочивания объектов между единицами перевода, группа зависимостей для объектов обычно явно не представлена. Однако, даже если зависимости были явно представлены, они на самом деле не сильно помогли бы: в небольших проектах зависимости между объектами со статической длительностью хранения могут быть относительно простыми. Где вещи становятся интересными, это большие объекты, но у них гораздо больше шансов включить инициализации формы
static T global = functionWhichMayuseTheword();
то есть, в случае, когда упорядочение было бы полезно, оно обязательно не работает.
Существует тривиальный способ убедиться, что объекты создаются во времени, который даже поточно-ориентирован в C ++ (он не был поточно-ориентированным в C ++ 03, так как в этом стандарте вообще не упоминалось понятие потоков) : Использовать локальную функцию static
объект и вернуть ссылку на него. Объекты будут создаваться по требованию, но если между ними есть зависимости, это обычно приемлемо:
static T& global() {
static rc = someInitialization();
return rc;
}
Учитывая, что существует простой обходной путь, и ни предложение, ни рабочая реализация, демонстрирующие, что предложение действительно работает, мало интереса для изменения состояния инициализации глобальных объектов. Не говоря уже о том, что улучшение поддержки глобальных объектов кажется столь же полезным, как создание goto
лучше.
Я не автор компилятора, поэтому возьмите то, что я говорю, с долей соли. Я думаю, что причины заключаются в следующем.
1) Желание сохранить модель C отдельной компиляции. Анализ времени ссылки, безусловно, разрешен, но я подозреваю, что они не хотели делать это необходимым.
2) Meyers Singleton (особенно теперь, когда он стал поточно-ориентированным) предоставляет достаточно хорошую альтернативу, поскольку его почти так же легко использовать, как глобальной переменной, но он предоставляет гарантии, которые вы ищете.