TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.37K subscribers
Post #279 3.94K
​Еще одно отличие С от С++

Это вот прям такое, мажорное отличие. Скажете его на собесе - все охренеют, вам руку пожмут через вебку и возьмут вас на работу сразу же(но это не точно).

В языке С нет проблемы Static initialization order fiasco!

Как же так? В С тоже есть статики и тоже есть разные единицы трансляции. Почему так?

All the expressions in an initializer 
for an object that has static storage
duration or in an initializer list for an
object that has aggregate or union type
shall be constant expressions.


Таким образом, в С статическая переменная со скалярным типом может быть инициализирована только константным выражением. Это не constexpr, а просто выражение, которое компилятор в состоянии вычислить во время компиляции. Если тип переменной представляет собой массив со скалярным типом элемента, то каждый инициализатор должен быть константным выражением и так далее. Поскольку такие выражения не могут ни вызывать побочных эффектов, ни зависеть от побочных эффектов, вызванных любыми другими вычислениями, изменение порядка вычисление константных выражений не влияет на результат. А значит и никакого фиаско нет!

Единственные неконстантные выражения, которые могут быть вычислены перед main, - это те, которые вызываются из среды выполнения C
. Вот почему объекты FILE, на которые указывают stdin, stdout и stderr, уже доступны для использования сразу же после начала main.

Стандартный C не позволяет пользователям регистрировать свой собственный код запуска перед основным, хотя GCC предоставляет расширение под названием constructor (возможна массонская связь с конструкторами из C++), которое вы можете использовать для воссоздания SIOF в C. Но это, как говорится, НЕСТАНДАРТ и у каждого свой путь в могилу.

Целью Страуструпа было сделать пользовательские типы пригодными для использования везде, где есть встроенные типы. Это означало, что C++ должен был разрешать глобальным переменным быть кастомными типами, что означает, что их конструкторы будут вызываться во время запуска программы. Поскольку в начале C++ не было функций constexpr, такие вызовы конструкторов никогда не могли быть постоянными выражениями. И так, родилось чудовище, погубившее много наших ребят - Static initialization order fiasco.

В процессе стандартизации C++ вопрос о порядке выполнения статической инициализации был спорной темой. Я думаю, что вы согласитесь с тем, что идеальная ситуация - это когда каждая статическая переменная была инициализирована до ее использования. К сожалению, для этого требуется технология компоновки, которой в те дни не существовало (и, вероятно, до сих пор не существует?). Инициализация статической переменной может включать вызовы функций, и эти функции могут быть определены в другой TU, что означает, что вам нужно будет выполнить анализ всей программы, чтобы успешно отсортировать статические переменные в порядке зависимостей. Стоит отметить, что даже если бы C++ мог быть разработан таким образом, он все равно не полностью предотвратил бы проблемы с порядком инициализации. Представьте, если бы у вас была какая-то библиотека, где предварительным условием функции использования было то, что функция init() была вызвана в какой-то момент в прошлом и повлияла на нужную для инициализацию переменную. Компилятор не может увидеть такие зависимости, которые есть только у программиста в голове. По коду этого совсем не видно. Поэтому, думаю, что даже полноценный анализ кода не помог бы решить проблему.

В конечном счете, ограниченные гарантии порядка инициализации, которые мы получили в C++98, были лучшими, которые мы могли получить в данных обстоятельствах. С помощью народного "а вот сделали бы по-человечески", возможно, многие из нас высказали пару ласковых о том, что тот стандарт не был полным без функций constexpr и что статические переменные должны иметь только константную инициализацию. Но такого рода размышления надо оставить это нытикам и нюням. А настоящие программисты прогают на том, что есть. В тех условиях, в которых возможно.

Don't complain to your life. Work on it and stay cool.

#cppcore #goodoldc
  • 🔥 24
  • 👍 13
  • 🤯 6
  • ❤ 5
  • 🤮 1
  • 😭 1
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →