何时调用 constinit 对象的析构函数?

Hel*_*sel 6 c++ destructor initialization-order c++20 constinit

一般说静态对象的析构函数是以与构造函数相反的顺序调用的。据我了解,constinit 对象是在编译时初始化的,因此它们的析构函数应该在“普通”静态对象的析构函数之后调用。

该程序

struct A
{
  constexpr A(const char* t): t_(t) {}
  ~A() {std::cout << "~A(" << t_ << ")\n";} 
  const char* t_;
};  

static A a1("static");  

int main () {
   static constinit A a2("constinit");  
   return 0;
} 
Run Code Online (Sandbox Code Playgroud)

(使用 GCC 10),但是,给出输出

~A(constinit)
~A(static)
Run Code Online (Sandbox Code Playgroud)

即 constinit 对象在“正常”静态对象之前被销毁(尽管它是更早构造的)。“逆序”规则对 constinit 对象不再有效吗?

Oli*_*liv 5

这两个a1a2常数初始化。的constinit说明符仅断言所定义的变量是恒定初始化。因此,这里a1以前被初始化a2因此a2被破坏之前a1预期。

“逆序”规则对constinit对象不再有效吗?常量初始化对象和动态初始化对象之间不存在倒序规则:即使常量初始化对象的构建发生在动态初始化对象的构建之前,常量初始化对象的销毁也像它们已经被动态初始化一样:[basic.start.术语]/3

如果对象是静态初始化的,则对象的销毁顺序与对象是动态初始化的顺序相同。