【问题标题】:When is the destructor of a constinit object called?什么时候调用 constinit 对象的析构函数?
【发布时间】:2020-11-05 17:40:44
【问题描述】:

一般说静态对象的析构函数是按照构造函数的相反顺序调用的。据我了解,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 对象不再有效吗?

【问题讨论】:

  • 我不得不重新审视标准,这不是编译器错误,常量初始化对象被破坏,就好像它们被动态初始化一样,这是在标准中指定的。违反逆序规则是符合标准的。

标签: c++ destructor c++20 initialization-order constinit


【解决方案1】:

a1a2 都是常量初始化的constinit 说明符仅断言所定义的变量是常量初始化的。所以这里a1a2 之前初始化,所以a2a1 之前被销毁,正如预期的那样。

“倒序”规则对constinit对象不再有效吗?倒序规则不在常量初始化对象和动态初始化 对象:即使常量初始化对象的构造发生在动态初始化对象的构造之前,常量初始化对象的销毁也会按照动态初始化的顺序进行:[basic.start.term]/3

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

【讨论】:

    猜你喜欢
    • 2019-04-07
    • 2015-09-23
    • 2016-02-24
    • 1970-01-01
    • 2021-02-16
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多