cppreference说std::atexit
:
可以与具有静态存储持续时间的对象的销毁同时调用这些函数,并且保证如果在B的注册之前对A的注册进行了测序,则对B的调用进行排序。对A的调用同样适用于静态对象构造函数和调用atexit
之间的顺序
我理解这段话意味着,如果在静态初始化期间调用std::atexit
,则在破坏静态对象之前将调用已注册的函数,该静态对象在上次初始化时静态对象被破坏。注册该函数的{1}}被调用。我还解释“可以同时调用”来表示静态对象析构之间可能发生的调用,而不是对单词的多线程解释。
我想知道的是,在初始化开始或完成时,对象是否被视为已初始化(在此排序的上下文中)。我写了一个简短的测试来测试这个:
std::atexit
我得到的输出是(http://cpp.sh/3bllu):
#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;
}
这让我相信ctor
dtor
atexit
在构造完成之前不会被认为是在这种情况下被初始化的。换句话说,该函数被认为是在my_foo
初始化之前注册的,因此注册函数在my_foo
被破坏后执行。
我似乎找不到任何可以保证这种行为的东西,我甚至不完全确定我对引用段落的初步解释是正确的。我描述的行为是我可以依赖的,还是实现定义的行为,甚至是未定义的行为?
答案 0 :(得分:7)
对析构函数的调用将在调用传递给atexit
的函数之前发生。来自[basic.start.term],第5页:
如果在完成之前对
std::atexit
的呼叫强烈发生 在具有静态存储持续时间的对象的初始化中,对对象的析构函数的调用被排序 在调用函数之前传递给std::atexit
。