编译器默认生成的构造函数是否为constexpr?相关代码合规性问询
让我逐个解答你的问题:
问题1:编译器生成的构造函数默认是constexpr的吗?
不是无条件默认的——编译器只会在完全满足constexpr构造函数的所有要求时,才会将隐式生成的构造函数(比如默认构造、拷贝构造、移动构造)声明为constexpr。
以C++14标准为例,隐式生成的默认构造函数被标记为constexpr的前提是:
- 所有直接基类的默认构造函数都是constexpr;
- 每个非静态数据成员的默认构造函数(如果有的话)都是constexpr;
- 构造函数本身满足constexpr构造函数的其他规则(比如函数体是
=default、没有try块、不包含不允许的操作等)。
举两个直观的例子:
// 例1:满足所有条件,隐式默认构造函数是constexpr struct Bar { constexpr Bar() = default; }; struct Foo { Bar b; }; constexpr Foo f; // 合法,因为Foo的默认构造是constexpr // 例2:不满足条件,隐式默认构造函数不是constexpr struct Baz { int x; }; // constexpr Baz b; // 非法,因为int的默认初始化无法在常量表达式中产生确定值,Baz的默认构造不是constexpr
问题2:这段代码的编译行为是否符合C++14标准?
是的,clang++ 3.8.0和g7.2.0的编译行为完全符合C14标准,哪怕给Foo添加int i;这类成员也一样。我们来拆解原因:
首先看代码:
struct Foo { constexpr operator bool() const { return false; } }; int main() { constexpr bool b = Foo{}; (void)b; }
核心逻辑是用Foo{}(临时Foo对象)初始化constexpr bool b,这要求整个转换过程是常量表达式。我们分两步分析:
Foo的隐式默认构造函数是否是constexpr?
- 当Foo没有成员时:没有基类、没有非静态成员需要初始化,完全满足C++14对隐式constexpr构造函数的要求,所以默认构造是constexpr的,
Foo{}可以在常量表达式中创建。 - 当Foo添加
int i;时:隐式生成的默认构造函数会对i做默认初始化,但C++14允许constexpr构造函数默认初始化内置类型——只要后续没有在常量表达式中读取这个未初始化的成员。而我们的转换运算符operator bool()根本没有访问i,所以这个构造过程依然符合常量表达式的要求。
- 当Foo没有成员时:没有基类、没有非静态成员需要初始化,完全满足C++14对隐式constexpr构造函数的要求,所以默认构造是constexpr的,
转换过程是否是常量表达式?
Foo的operator bool()被声明为constexpr,且函数体只是返回常量false,完全符合constexpr函数的规则。结合第一步中Foo{}是合法的常量表达式构造,整个Foo{} -> bool的转换过程属于常量表达式,因此可以用来初始化constexpr bool b。
综上,这段代码在C++14下是完全合规的,编译器的行为没有问题。
内容的提问来源于stack exchange,提问作者Constructor
相关产品推荐
相关产品推荐

