cppreference говорит о std::atexit
:
Функции могут вызываться одновременно с уничтожением объектов со статической продолжительностью хранения и друг с другом, сохраняя гарантию того, что если регистрация A была упорядочена до регистрации B, то вызов B упорядочен до вызов A, то же самое относится к последовательности между конструкторами статических объектов и вызовам 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
.
Кажется, я не могу найти ничего, что гарантировало бы такое поведение, и я даже не совсем уверен, что моя первоначальная интерпретация цитируемого отрывка верна. Является ли описанное мной поведение чем-то, на что я могу положиться, или оно определяется реализацией или даже неопределенным поведением?