Я столкнулся с this question, спрашивая, как выполнить код перед main() в C, отметив, что существуют стратегии для C++. Я в основном жил в прикладном пространстве, поэтому выполнение перед тем, как main() мне никогда не приходило в голову. Какие вещи требуют этой техники?Какие операции можно было бы выполнить до main()
ответ
«Какие вещи требуют этой техники?»
Точка зрения: нет.
Однако есть много полезных вещей, которые вы, возможно, захотите сделать до начала по разным причинам. Для всего лишь одного практического примера, скажем, у вас есть абстрактная фабрика, которая строит doohickies. Вы можете убедиться в том, чтобы создать заводский экземпляр, назначить его в какую-то специальную область, а затем зарегистрировать различные конкретные дохины ... да, вы можете это сделать.
С другой стороны, если вы реализуете фабрику в качестве одноэлементного устройства и используете факты инициализации глобального значения, чтобы «обмануть» реализацию, зарегистрировав конкретные догадки до начала запуска, вы получите несколько преимуществ с очень небольшим количеством затрат (факт использование одиночных игр, в основном без проблем здесь, в значительной степени является единственным).
Например, вы:
Не должны поддерживать список регистраций, которые все должны быть явно называется. Фактически, вы даже можете объявить и определить весь класс в закрытом поле зрения, вне поля зрения кого-либо, и иметь его доступным для использования при запуске программы.
main() не нужно делать кучу дерьма с кучей объектов, на которые он не заботится.
Таким образом, все это не на самом деле необходимо. Тем не менее, вы можете уменьшить проблемы связи и обслуживания, если вы используете тот факт, что глобальные переменные инициализируются до начала основного.
Edit:
Должен отметить, что я так понял, что это не гарантируется языком.C++ только гарантирует, что ноль или постоянный инициализация происходит до main. О чем я говорю в этом ответе, является динамический инициализации. Эти гарантии C++ выполняются до первого использования переменной, подобно функциям-локальным статическим переменным.
Каждый компилятор, кажется, выполняет динамическую инициализацию перед основным. Я думал, что однажды столкнулся с одним, но я считаю, что источником проблемы было что-то еще.
+1, это единственное, что у меня есть для этого ... но мальчик я его использую! –
Этот метод может быть использован для инициализации библиотеки или для инициализации данных, которые будут использоваться неявно во время выполнения программы.
GCC обеспечивает конструктор и деструкторfunction attributes, которые вызывают функцию, которая будет вызвана автоматически до исполнения входит main()
или main()
завершил или exit()
был назван, соответственно.
void __attribute__ ((constructor)) my_init(void);
void __attribute__ ((destructor)) my_fini(void);
В случае инициализации библиотеки, конструктор подпрограммы выполняются до dlopen()
возвращается, если библиотека загружается во время выполнения или перед main()
запускается, если библиотека загружается во время загрузки. Когда используется для очистки библиотеки, процедуры деструктора выполняются до того, как возвращается dlclose()
, если библиотека загружается во время выполнения или после exit()
или по завершении main()
, если библиотека загружается во время загрузки.
Если у вас есть библиотека, очень удобно иметь возможность инициализировать некоторые данные, создавать потоки и т. Д. Перед вызовом main() и знать, что желаемое состояние достигается без отягощения и доверия к клиентскому приложению вызвать некоторую инициализацию библиотеки и/или код завершения. Поверхностно это может быть достигнуто за счет наличия статического объекта, конструктор и деструктор которого выполняет необходимые операции. К сожалению, несколько статических объектов в разных единицах перевода или библиотеках будут иметь неопределенный порядок инициализации, поэтому, если они зависят друг от друга (что еще хуже, циклически), они могут все еще не достигнуть своего инициализированного состояния до того, как появится запрос in. Аналогично, один статический объект может создавать потоки и вызывать службы в другом объекте, которые еще не являются потокобезопасными. Таким образом, более строгий подход с правильными экземплярами singleton и блокировками необходим для обеспечения устойчивости в условиях произвольного использования, и все это выглядит гораздо менее привлекательным, хотя в некоторых случаях это может быть чистая победа.
Материал сделано до главной:
- На x86, стек регистр указателя обычно & = 0XF3, чтобы сделать его кратным 4 (выравнивание)
- Статические члены инициализируются
- толчок ARGC и ARGV (и Environ при необходимости)
- вызова _Главная = р
г ++ 4.4 выдает следующую BEF если какой-либо из моих кодов испускается. Технически он вставляет его в верхнюю часть main
до любого из моего кода, но я видел компиляторов, которые используют _init
вместо _main
в качестве точки входа:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
# My code follows
Единственное, что вам хотелось бы иметь, чтобы сделать, прежде чем main
включать глобальные переменные, которые являются плохими, и одни и те же вещи всегда могут выполняться ленивой инициализацией (инициализация в точке первого использования). Конечно, их было бы намного лучше, если бы не использовать глобальные переменные вообще.
Одним из возможных «исключений» является инициализация глобальных таблиц констант во время выполнения. Но это очень плохая практика, поскольку таблицы не разделяются между экземплярами библиотеки/процесса, если вы их заполняете во время выполнения. Гораздо умнее писать сценарий для генерации таблиц static const
в качестве исходного файла C или C++ во время сборки.
Все, что необходимо для запуска кода для гарантии инвариантов для вашего кода после запуска main
, должно запускаться до main
. Такие вещи, как глобальные iostreams, библиотека времени выполнения C, привязки ОС и т. Д.
Теперь, действительно ли вам нужно писать код, который делает такие вещи, это то, что все остальные отвечают.
- 1. Как можно было бы заморозить или перечислить все virtualenvs?
- 2. в SpriteKit, возможно ли выполнить операции «на лету», как если бы действие группировки было измененным массивом.
- 3. Какой тип алгоритма можно было бы назвать?
- 4. Когда можно было бы использовать mysqli_ping?
- 5. Как можно было бы использовать цикл for?
- 6. Где можно было бы использовать в Цейлоне
- 7. Как можно было бы создать список наблюдения?
- 8. Как можно было бы генерировать неиспользуемый столб?
- 9. C# - Можно ли инициализировать до начала Main?
- 10. Можно выполнить откат после выполнения операции фиксации
- 11. , упрощающий вычисление, поэтому его можно было бы выполнить с использованием матричных операций
- 12. Что было бы условия?
- 13. Где можно было бы начать учиться создавать программы визуализатора?
- 14. SOLR/Lucene: Как можно было бы расширить класс Scorer s.t. его можно было бы обернуть в плагин Solr
- 15. Что было бы альтернативой параметрам?
- 16. Какой тип логики игры можно было бы назвать?
- 17. Какие операции можно выполнять параллельно, не захватывая GIL?
- 18. Выполнение кода до main()
- 19. было бы возможно
- 20. Что было бы наоборот CGRectUnion()?
- 21. Было бы полезно узнать OpenGL?
- 22. Операции ввода-вывода - Почему бы не cd?
- 23. Как можно было бы запустить скрипт python на всех платформах?
- 24. как можно было бы напечатать итератор в C++?
- 25. Как этот базовый HTML можно было бы вывести из Node.js?
- 26. Когда`starmap` можно было бы пореже над `List Comprehension`
- 27. Как можно было бы нарисовать повторяющиеся фоны на этом спрайте?
- 28. Какой самый простой счетчик посещений, который можно было бы сделать?
- 29. Как можно было бы векторизовать это несколько циклов в Matlab?
- 30. Когда можно было бы оправдывать переопределение ориентации обработки
Вещи, которые не должны быть выполнены. –
Это было интересно: http: // stackoverflow.com/questions/4783404/is-main-really-start-of-a-c-program – Dave