小编典典

`constexpr` 和 `const` 之间的区别

all

constexpr和有什么区别const

  • 我什么时候可以只使用其中之一?
  • 我什么时候可以同时使用,我应该如何选择一个?

阅读 179

收藏
2022-03-02

共1个答案

小编典典

基本含义和语法

这两个关键字都可以在对象和函数的声明中使用。应用于 对象 时的基本区别是:

  • const将对象声明为 常量 。这意味着保证一旦初始化,该对象的值就不会改变,编译器可以利用这一事实进行优化。它还有助于防止程序员编写修改初始化后不打算修改的对象的代码。

  • constexpr声明一个对象适合在标准所称的 常量表达式 中使用。但请注意,这constexpr不是唯一的方法。

当应用于 函数 时,基本区别是:

  • const只能用于非静态成员函数,一般不能用于函数。它保证成员函数不会修改任何非静态数据成员(可变数据成员除外,无论如何都可以修改)。

  • constexpr可以与成员函数和非成员函数以及构造函数一起使用。它声明函数适合在 常量表达式 中使用。如果函数满足某些标准(7.1.5/3,4),编译器才会接受它,最重要的是(’):

    • 函数体必须是非虚拟的并且非常简单:除了 typedef 和静态断言之外,只return允许使用一条语句。在构造函数的情况下,只允许使用初始化列表、typedef 和静态断言。(不过= default= delete也被允许。)
    • 从 C++14 开始,规则更加宽松,从那时起在 constexpr 函数中允许的内容:asm声明、goto语句、带有除caseand以外标签的语句default、try-block、非文字变量的定义类型,静态或线程存储持续时间的变量的定义,不执行初始化的变量的定义。
    • 参数和返回类型必须是 文字类型 (即,一般来说,非常简单的类型,通常是标量或聚合)

常量表达式

如上所述,constexpr声明对象和函数都适合在常量表达式中使用。常量表达式不仅仅是常量:

  • 它可以用于需要编译时评估的地方,例如,模板参数和数组大小说明符:

      template<int N>
    

    class fixed_size_list
    { // };

    fixed_size_list mylist; // X must be an integer constant expression

    int numbers[X]; // X must be an integer constant expression

  • 但请注意:

  • 将某些东西声明为constexpr不一定保证它将在编译时进行评估。它 可以用于 此类,但也可以用于在运行时评估的其他地方。

  • 一个对象 可以在 没有 被声明的情况下适用于常量表达式constexpr。例子:

         int main()
     {
       const int N = 3;
       int numbers[N] = {1, 2, 3};  // N is constant expression
     }
    

这是可能的N,因为 是常量并在声明时用文字初始化,满足常量表达式的条件,即使它没有被声明constexpr

那么我什么时候必须使用constexpr呢?

  • 像上面这样的 对象N可以用作常量表达式 而无需 声明constexpr。这适用于所有对象:
  • const
  • 整数或枚举类型
  • 在声明时使用本身是常量表达式的表达式初始化
2022-03-02