在常量初始化程序中调用constexpr构造函数的限制

时间:2014-06-30 14:15:15

标签: c++

我不理解constexpr constructor调用的以下内容:

  

对象o的常量初始值设定项是一个表达式   常量表达式,除了它还可以调用 constexpr   o及其子对象的构造函数,即使这些对象是   非文字类类型

Constexpr构造函数本身是核心常量表达式:

  

条件表达式e是核心常量表达式,除非   评估e,遵循抽象机的规则(1.9),   将评估以下表达式之一:

     

[...]

     

- 一个调用   对于文字类,函数而不是constexpr构造函数,   constexpr函数,或者是一个简单的隐式调用   析构函数(12.4)[...]

1 个答案:

答案 0 :(得分:0)

随后的说明中有一些实质性暗示:

  

[注意:这样的类可能有一个非平凡的析构函数 - 结束语]

回想一下文字类型(3.9p10):

  
      
  • 有一个简单的析构函数,
  •   
  • 是聚合类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板,它不是复制或移动构造函数,而且
  •   
  • 它的所有非静态数据成员和基类都是非易失性文字类型。
  •   

因此,如果一个类有一个非平凡的析构函数,它就被取消了作为文字类的资格,但是对其constexpr构造函数的调用仍然可以作为一个常量初始化程序:

#include <iostream>
struct A {
    int count = 0;
    constexpr A() {}
    ~A() { std::cout << "~A: " << count << std::endl; }
};
A a;

然后,即使a不是文字类类型,程序也可以在进行任何动态初始化之前依赖A进行初始化。

基本原理是因为虽然A的析构函数有副作用,但在初始化期间不会调用它,因此编译器可以计算适当的初始内存内容在编译时a(实际上,它是.data)。


请注意,您在第二个引用中的重点是不完整的;相关术语是“一个constexpr构造函数,用于文字类 ”。