8

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' 的销毁之后执行。

我似乎找不到任何可以保证这种行为的东西,我什至不完全确定我对引用段落的初步解释是正确的。我描述的行为是我可以依赖的东西,还是实现定义甚至未定义的行为?

4

1 回答 1

7

对析构函数的调用将发生在对传递给的函数的调用之前atexit。来自 [basic.start.term],p5:

如果在std::atexit具有静态存储持续时间的对象的初始化完成之前对 strong 的调用发生,则对对象的析构函数的调用将在对传递给的函数的调用之前进行排序std::atexit

于 2018-05-16T20:03:25.473 回答