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

7

通常认为静态对象的析构函数是按照构造函数相反的顺序调用的。根据我的理解,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;
} 

(使用GCC 10)然而,输出结果为:
~A(constinit)
~A(static)

即constinit对象在“普通”静态对象之前被销毁(尽管它的构造早于后者)。对于constinit对象,这个“倒序规则”不再适用吗?

我不得不重新查看标准,这不是编译器错误,常量初始化对象被销毁就像它们是动态初始化的一样,在标准中有明确规定。违反反向顺序规则符合标准。 - Oliv
1个回答

7
a1a2都是常量初始化的。 constinit关键字仅断言正在定义的变量是常量初始化的。因此,在这里a1a2之前初始化,所以a2按预期在a1之前被销毁。 对于constinit对象,“反向顺序”规则不再有效吗? 反向顺序规则不存在于常量初始化对象和动态初始化对象之间:即使常量初始化对象的构造发生在动态初始化对象之前,常量初始化对象的销毁顺序也会按照它们已经被动态初始化一样进行排序: [basic.start.term]/3

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接