упорядочение std :: atexit при вызове из конструктора глобального объекта - PullRequest
0 голосов
/ 16 мая 2018

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.

Кажется, я не могу найти ничего, что гарантировало бы такое поведение, и я даже не совсем уверен, что моя первоначальная интерпретация цитируемого отрывка верна. Является ли описанное мной поведение чем-то, на что я могу положиться, или оно определяется реализацией или даже неопределенным поведением?

1 Ответ

0 голосов
/ 16 мая 2018

Вызов деструктора произойдет до того, как вызов функции будет передан atexit. Из [basic.start.term], p5:

Если вызов std::atexit сильно происходит до завершения инициализация объекта со статической продолжительностью хранения, вызов деструктора для объекта перед вызовом функции передается std::atexit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...