为何从非constexpr变量初始化类类型constexpr变量可成功?
为什么类类型的constexpr变量可以用非constexpr对象初始化?
核心原因是内置类型和类类型的constexpr初始化规则存在本质差异,具体拆解如下:
1. 内置类型的constexpr初始化要求
对于int这类内置类型,constexpr变量的初始化值必须是常量表达式——也就是能在编译期完全确定的值。
像int i = 0;中的i是运行期变量(它的存储和值只有在程序运行时才确定),所以constexpr int j = i;会编译失败,因为编译器无法在编译期获取i的值,不符合内置类型constexpr变量的初始化要求。
2. 类类型的特殊处理逻辑
你的例子里的struct C是一个空结构体,它的行为符合C++对constexpr类的默认规则:
- 编译器会为
C隐式生成一个constexpr拷贝构造函数——因为空结构体的拷贝构造不需要依赖任何运行期数据,满足constexpr构造函数的条件(所有成员都能constexpr初始化,构造过程无副作用)。 - 当你写
constexpr C d = c;时,调用的是这个constexpr拷贝构造函数。由于C是空结构体,拷贝它的过程不需要读取c的任何实际内容——不管c是运行期还是编译期对象,编译器都能直接在编译期生成一个空的C对象,完全不依赖c的运行状态。
这种情况下,初始化过程可以在编译期完成,自然符合constexpr变量的要求。
补充验证:如果类有非平凡成员呢?
如果给C添加一个需要运行期值的成员,比如:
struct C { int x; }; int main() { int i = 0; C c{1}; constexpr C d = c; // 这里会编译失败 }
此时拷贝构造需要读取c.x的值,而c.x是运行期变量,编译器无法在编译期确定它的值,所以这条语句就会和内置类型的情况一样编译失败,这也反过来验证了前面的逻辑。
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

