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

标签 c++ language-lawyer static-initialization atexit initialization-order

cppreference 表示 std::atexit :

The functions may be called concurrently with the destruction of the objects with static storage duration and with each other, maintaining the guarantee that if registration of A was sequenced-before the registration of B, then the call to B is sequenced-before the call to A, same applies to the sequencing between static object constructors and calls to 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 销毁后执行。

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

最佳答案

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

If a call to std::atexit strongly happens before the completion of the initialization of an object with static storage duration, the call to the destructor for the object is sequenced before the call to the function passed to std::atexit.

关于c++ - 从全局对象的构造函数调用时的 std::atexit 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50378923/

相关文章:

C++ 运算符重载和访问私有(private)数据变量

c++ - 我是否正确实现了时钟漂移?

c++ - 为什么 Foo(b) 在 C++ 中编译成功?

c++ - `char16_t` 和 `char32_t` 是用词不当吗?

c++ - 如何保证模板结构中 const 静态成员的初始化顺序

Java:静态初始化 block 什么时候有用?

c++ - 面向对象设计——最简单的情况,但我还是很困惑!

c++ - 如何评估前缀和后缀运算符的组合

c - C99 标准是否允许将变量分配给自身?

Go中的静态初始化?