B中。 Stroustrup在他的书“TCPL”第4版的第265页上有以下示例:
struct Point{
int x, y, z;
constexpr Point up(int d) { return {x, y, z+d}; }
constexpr Poind move(int dx, int dy) { return {x+dx, y+dy}; }
};
后来他在第266页显示:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
根据N4140的§7.1.5/ 4,我找到以下相关要点:
- (4.4)其函数体应为
= default
,或其函数体的复合语句应满足约束 对于constexpr函数的函数体;- (4.5)应初始化每个非变量非静态数据成员和基类子对象(12.6.2);
关于上述要点,我有两点意见:
struct Point
的编译器生成的默认构造函数是否具有函数体= default
是否正确?yes
,我也反驳说编译器为struct Point
生成的默认构造函数是constexpr
,这只是因为这个构造函数没有初始化成员x
,y
和z
,与上面的要点(4.5)相矛盾。我在这里纠正吗?编辑我正在介绍第三个问题,我认为我总结了这个问题的主要难点。
我无法生成一个constexpr
默认构造函数的示例,其构造函数等于= default
。假设这是不可能的。显而易见的问题是:§7.1.5/ 4中的要点(4.4)的目的是什么?
答案 0 :(得分:5)
如果没有用户声明的构造函数 对于类
X
,没有参数的非显式构造函数被隐式声明为为默认值(8.4)。
隐式声明为默认值的函数意味着它的功能就像它被显式声明为= default
一样。
constexpr
,通过[dcl.init]进一步说明:如果程序要求对const限定类型T的对象进行默认初始化,则T应为类类型 使用用户提供的默认构造函数。
因此,以下内容不正确,因为没有用户提供的默认构造函数:
constexpr Point p; // error
我们也在[dcl.constexpr]中看到了这一点:
对象声明中使用的
constexpr
说明符将对象声明为const
。这样的对象应该有 文字类型和应初始化。如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.20)。否则,或者如果在引用声明中使用constexpr
说明符,则每次完整表达式 出现在其初始化程序中的应该是一个常量表达式。 [注意:每次隐式转换 用于转换初始化表达式和用于初始化的每个构造函数调用都是其中的一部分 如此全面的表达。 -end note]
[例如:struct pixel { int x, y; }; constexpr pixel ur = { 1294, 1024 }; // OK constexpr pixel origin; // error: initializer missing
-end example]
由于默认构造函数没有为我们初始化(即使它没有使用户提供的要求失败),我们可以提供一个初始化程序来自己完成:
constexpr Point q{}; // ok, all of q's members are 0
这最终无关紧要:
constexpr Point p1 {10, 20, 30}; // the default constructor is constexpr
根本不使用默认构造函数,实际上执行聚合初始化,满足"应该初始化"上面引用的条款。