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

Restriction for invocation of constexpr constructor in a constant initializer

本文关键字:构造函数 constexpr 调用 常量 初始化      更新时间:2023-10-16

我不明白constexpr constructor调用的以下添加:

对象0的常量初始化式是A的表达式常量表达式,除了它也可以调用constexpr构造函数用于0及其子对象,即使这些对象是of非文字类类型

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

条件表达式e是核心常量表达式,除非对e求值,遵循抽象机(1.9)的规则,将计算下列表达式之一:

[…)

-一个调用对于文字类,除了constexpr构造函数之外的函数,一个constexpr函数,或者一个微不足道的函数的隐式调用析构函数(12.4)[…]

在后面的注释中有一个重要的提示:

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

回想一下文字类类型(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构造函数用于文字类"。