cppreference говорит о std::atexit
:
Функции могут вызываться одновременно с уничтожением объектов со статической продолжительностью хранения и друг с другом, сохраняя гарантию того, что если последовательность A была упорядочена до регистрации B, то вызов B упорядочен до вызова А, то же самое относится к последовательности между конструкторами статических объектов и вызовами atexit.
Я понимаю, что этот отрывок означает, что если std::atexit
вызывается во время статической инициализации, зарегистрированная функция будет вызываться во время уничтожения статических объектов непосредственно перед уничтожением статического объекта, который был последний раз инициализирован, когда std::atexit
которая зарегистрировала функцию была вызвана. Я также интерпретирую «могут быть вызваны одновременно», чтобы означать, что вызовы могут происходить между разрушением статических объектов, в отличие от многопоточной интерпретации слова.
Что мне интересно, так это то, считается ли объект инициализированным (в контексте этого порядка), когда начинается его инициализация или когда он завершается. Я написал короткий тест, чтобы проверить это:
#include <cstdlib>
#include <iostream>
struct foo
{
foo()
{
std::cout << "ctor\n";
std::atexit([]() { std::cout << "atexit\n"; });
}
~foo()
{
std::cout << "dtor\n";
}
};
foo my_foo;
int main()
{
return 0;
}
Вывод, который я получаю (http://cpp.sh/3bllu):
ctor
dtor
atexit
Это заставляет меня верить, что my_foo
не считается инициализированным в этом контексте, пока не завершится его построение. Другими словами, функция считается зарегистрированной ранее my_foo
была инициализирована, поэтому зарегистрированная функция выполняется после my_foo
Разрушение
Кажется, я не могу найти ничего, что гарантировало бы такое поведение, и я даже не совсем уверен, что моя первоначальная интерпретация процитированного отрывка верна. Является ли описанное мной поведение чем-то, на что я могу положиться, или это определенная реализация или даже неопределенное поведение?
Вызов деструктора произойдет до того, как вызов функции будет передан atexit
, Из [basic.start.term], стр. 5:
Если звонок в
std::atexit
сильно случается до завершения
инициализация объекта со статической продолжительностью хранения, вызов деструктора для объекта
до вызова функции передаетсяstd::atexit
,
Других решений пока нет …