std::atexit 从全局对象的构造函数调用时的排序



cpp首选项说std::atexit

这些函数可以与具有静态存储持续时间的对象销毁同时调用,并相互调用,从而保证如果 A 的注册是排序的 - 在 B 注册之前,那么对 B 的调用是排序的 - 在调用 A 之前,同样适用于静态对象构造函数和 atexit 调用之间的排序

我理解这段话的意思是,如果在静态初始化期间调用std::atexit,则在销毁静态对象之前,将在销毁静态对象期间调用注册的函数,该静态对象上次初始化时注册函数被调用std::atexit被调用。我还将"可以并发调用"解释为调用可以在静态对象销毁之间发生,而不是对该词的多线程解释。

我想知道的是,当一个对象开始初始化或完成时,它是否被视为已初始化(在此排序的上下文中)。我写了一个简短的测试来测试这一点:

#include <cstdlib>
#include <iostream>
struct foo
{
foo() 
{
std::cout << "ctorn";
std::atexit([]() { std::cout << "atexitn"; });
}
~foo()
{
std::cout << "dtorn";
}
};
foo my_foo;
int main()
{
return 0;
}

我得到的输出是(http://cpp.sh/3bllu):

ctor
dtor
atexit

这让我相信,my_foo在构造完成之前,不会被视为在这种情况下初始化。换句话说,该函数被认为在初始化之前my_foo已经注册,因此注册的函数在my_foo销毁后执行。

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

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

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

最新更新