c++ 为什么在类的情况下从非constexpr变量初始化constexpr变量成功

nafvub8i  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(129)

我学习过c++中的constexpr变量,读到int i =0; constexpr int j = i;失败是因为i不是常量表达式,这是有意义的,但是当我对类的变量做同样的操作时,它成功了。

struct C{};
int main()
{
    int i = 0; //i is not a constant expression as expected 
    //constexpr int j = i; //this fails AS EXPECTED

    C c; 
    constexpr C d = c; //WHY DOESN'T THIS FAIL?? 
}

正如您所看到的,constexpr C d = c;constexpr int j = i;不同,即使c也不是一个常量表达式,constexpr C d = c;也不会出现任何编译问题。
我想知道这背后的原因。

v440hwme

v440hwme1#

我想知道这背后的原因。
因为类C有一个隐式的constexpr复制构造函数constexpr C::C(const C&),可以像这样在constexpr上下文中使用。
基本上,初始化constexpr C d = c;是一个 *constexpr上下文 *,constexpr函数正是为此目的而设计的。
通过查看cppinsights中生成的代码,您也可以看到这一点:

struct C
{
  // inline constexpr C() noexcept = default;
  // inline constexpr C(const C &) noexcept = default;
};

正如我们在上面生成的代码中看到的,C隐式声明了可以在constexpr上下文中使用的constexpr构造函数。
constexpr开始:
constexpr变量必须满足以下要求:

  • ...
    *其初始化的完整表达式(包括所有隐式转换、构造函数调用等)必须是常量表达式
ecbunoof

ecbunoof2#

它是有效的,因为d的初始化不依赖于c的 * 值 *,因为c不包含运行时存在的数据。

struct A{
    static int x;
};

int A::x = 5;

struct B{
    int x = 5;
};

int main() {
    A a1;
    constexpr A a2 = a1; // a1 contains no runtime data: okay

    B b1;
    constexpr B b2 = b1; // b1 contains runtime data: error
}
g++ main.cpp 
main.cpp: In function ‘int main()’:
main.cpp:16:22: error: the value of ‘b1’ is not usable in a constant expression
   16 |     constexpr B b2 = b1; // a1 containes runtime data: error
      |                      ^~
main.cpp:15:7: note: ‘b1’ was not declared ‘constexpr’
   15 |     B b1;
      |       ^~

您可以在以下位置找到常量表达式的要求列表:

相关问题