在C ++中,您可以将许多内容声明为constexpr
:变量,函数(包括成员函数和运算符),构造函数,以及自C ++ 1z以来if
statements和lambda expressions 。但是,声明destructor constexpr
会导致错误:
struct X {
constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};
我的问题:
constexpr
?constexpr
吗?~X() = default;
),它会自动constexpr
吗?答案 0 :(得分:11)
根据draft basic.types#10可能具有以下所有属性的cv限定类类型:
可能具有cv限定的类类型,它具有以下所有属性:
(10.5.1) - 它有一个简单的析构函数,
(10.5.2) - 它是闭包类型,聚合类型或者有 至少一个constexpr构造函数或构造函数模板(可能 继承自基类),它不是复制或移动构造函数,
(10.5.3) - 如果它是一个联合,至少有一个非静态数据 成员是非易失性文字类型
(10.5.4) - 如果不是 一个union,它的所有非静态数据成员和基类都是 非易失性文字类型。
问题1:为什么析构函数不能被标记为constexpr?
因为只有琐碎的析构函数才有资格获得constexpr 以下是draft
的相关部分如果析构函数不是用户提供的,并且如果:
,则析构函数很简单(5.4) - 析构函数不是虚拟的,
(5.5) - 其类的所有直接基类都很简单 析构函数,
(5.6) - 对于其类的所有非静态数据成员 对于类类型(或其数组),每个这样的类都是微不足道的 析构函数。
否则,析构函数是非常重要的。
问题2:如果我不提供析构函数,是隐式生成的析构函数constexpr吗?
是的,因为隐式生成的析构函数是微不足道的类型,所以它有资格用于constexpr
问题3:如果我声明一个默认的析构函数(~X()= default;),它会自动constexpr吗?
实际上,这个析构函数是用户声明的并且是隐式生成的,因此它符合constexpr的条件。
我无法找到任何直接引用,只有琐碎的destructors
符合constexpr
的条件,但如果析构函数不是微不足道的话,那么确定类类型不是{{1}所以它是隐含的,因为你无法为cv-qualified.
类定义destructor
。
答案 1 :(得分:4)
如果您正在寻找的是限制背后的推理,请查看this paper明确指出限制是人为的 - 析构函数的内在属性无法阻止他们在constexpr上下文中工作,实际上编译器实现者同意在constexpr上下文中支持它们将很容易实现。
我猜C ++标准委员会最初将限制放在C ++ 11中,因为他们当时并不想处理析构函数,而且更容易完全排除它们。
答案 2 :(得分:3)
为什么析构函数不能被标记为constexpr?
C ++ 11标准特别针对使用const
构造和非静态成员函数。它没有说出任何关于析构函数的具体内容。可以假设析构函数将被视为非静态成员函数。
const
只能用于constexpr
成员函数。由于析构函数不能是constexpr
成员函数,因此无法将其限定为constexpr ~X() = default;
成员函数。
如果我不提供析构函数,则是隐式生成的析构函数
constexpr
。
使用
~X() = default;
是一个错误,我觉得编译器生成的析构函数不是constexpr
函数。我无法在标准中找到任何证据来证明我的陈述。我猜。
如果我声明了默认的析构函数(
struct X { constexpr X(int i) : i_(i) {} ~X() = default; int i_; }; int main() { const X x(10); }
),它会自动EditText
我想不是。再一次,我无法在标准中找到任何证据来证明我的陈述。我猜。
FWIW,g ++编译并构建以下程序就好了。
EditText
答案 3 :(得分:3)
从C ++ 20开始,可以将构造函数标记为constexpr
;我不知道它是否在任何地方都明确表示“析构函数可能是constexpr
”,但是draft standard在第9.2.5节第5段中包含以下文本:
其函数体不是
constexpr
的{{1}}析构函数的定义还应满足 以下要求:
- 对于类类型或其(可能是多维)数组的每个子对象,该类类型应 有一个constexpr析构函数。
这现在也具有有用的功能,因为C ++ 20还允许在= delete
上下文中使用new
和delete
,从而允许constexpr
和vector
之类的东西可以在没有黑客的情况下在编译时工作(尽管我相信C ++ 20实际上并未包括对标准库的更改以允许这样做,但是可以使用与string
相同的API和行为来实现某些功能,这些功能可以完全正常工作在编译时)。
答案 4 :(得分:2)
析构函数不能是constexpr
,因为constexpr
函数不能有副作用,根据定义,析构函数只能通过副作用使用。简而言之,拥有constexpr
的析构函数是没用的。
如果对象的析构函数不重要,则该对象不能为constexpr
。默认情况下,默认值为constexpr
析构函数声明(如果有)的decl-specifier-seq的每个decl-specifier应为
friend
,inline
或virtual
。
遗漏了constexpr
。所以你可以把它当作:因为标准说的是 TM
答案 5 :(得分:2)
Reference的标记:' s:
constexpr析构函数
在大多数情况下,为了在常量中创建类型T的对象 表达,T的破坏必须是微不足道的。但是,非平凡 析构函数是现代C ++的重要组成部分,部分原因在于 RAII习语的广泛使用,也适用于 constexpr评估。可以支持非平凡的析构函数 常量表达式,如下:
- 允许将析构函数标记为constexpr
- 如果他们只调用constexpr析构函数,则使默认析构函数成为constexpr
- 对于constexpr变量,要求评估析构函数是一个常量表达式(除了被销毁的对象可能是 在自己的析构函数中修改
但是,对于这样的功能,没有引人注目的用例,并且 将会有一个非常重要的实施成本确保这一点 析构函数在适当的时间运行。