C++ Constexpr

28 Aug 2024 | 5 分钟阅读

在 C++ 11 中,引入了一个名为 constexpr 的特性。其基本概念是通过在编译时而非运行时执行计算来提高软件性能。值得注意的是,消费者通常在开发人员完成编译和最终确定软件后多次运行它。目标是投入编译时间,同时节省运行时时间(类似于模板元编程)。Constexpr 表示对象或函数的值可以在编译时确定,并且该表达式可以用于其他常量表达式。

输出

200
.........
Process executed in 1.11 seconds
Press any key to continue.

const 限定符让程序员和编译器知道我们打算让变量是只读的,并且任何修改它的尝试都会导致编译错误。

在指示常量方面,constexpr 等同于 const。它也是不可变的。Const 的不同之处在于,根据我们初始化它的方式,它可以在编译时和运行时进行评估。

说明

  • C++ 11 中的 constexpr 函数应该只有一个 return 语句。在 C++ 14 中,允许多个语句。
  • constexpr 函数只能与常量全局变量一起使用。
  • constexpr 函数只能调用其他 constexpr 函数,而不能调用普通函数。
  • 函数的类型不应该是 void。
  • C++11 中不允许 constexpr 函数前缀递增 (++v);然而,此限制在 C++14 中已取消。

编写一个只返回给定整数乘积的 constexpr 函数可能看起来毫无意义。除了性能提升之外,这个特性的用途还可以在哪里找到?

  • 此特性的主要好处是它使我们能够使用函数评估编译时常量。通过这种方式,我们可以在编译时计算数组的大小,这在以前是不可行的。

输出

6
……..
Process executed in 1.11 seconds
Press any key to continue.

将设备从一个系统转换到另一个系统是另一个实际用例。例如,尽管大多数人觉得使用角度以度为单位更简单,但 C/C++ 中的三角函数接受以弧度为单位的角度。因此,我们可以将 ConvertDegreeToRadian() 方法定义为 constexpr,而不会牺牲代码的清晰性或效率。

输出

Angle in radian: 1.5708
………………………………….
Process executed in 0.11 seconds
Press any key to continue. 

Constexpr 与内联函数

constexpr内联函数
由于代码和表达式在编译期间进行评估,函数调用被移除。它几乎从不消除任何函数调用,因为它在运行时对表达式进行操作。
变量或函数的值可以在编译期间进行评估。函数或变量的值不能在编译时确定。
它不对外部链接做出推断。它建议一个外部链接。

Constexpr 性能提升示例

// 一个演示 constexpr 用法的 C++ 程序

输出

832040
………….
Process executed in 0.003 seconds
Press any key to continue.

如果我们从下面一行中删除 const,那么 fib(5) 的值不会在编译时进行评估,因为 constexpr 的结果没有在 const 表达式中使用。上述程序在 GCC 上运行时间为 0.003 秒(我们可以使用 time 命令测量时间)。

在进行上述修改后,程序的执行时间增加了 0.017 秒。

构造函数和 constexpr: 用 constexpr 说明符声明的构造函数被认为是 constexpr 构造函数。构造函数和对象也可以使用 constexpr 创建。constexpr 的构造函数被隐式地内联。

constexpr 用法的构造函数限制

  • 缺少虚基类
  • 每个参数都必须是字面量。
  • 函数不是 try-block 函数。

输出

200
……..
Process executed in 0.17 seconds
Press any key to continue.

Constexpr 与 const

它们具有不同的功能。Const 用于几乎不变的事物,如 Pi 的值,而 constexpr 主要用于效率。成员方法可以使用其中任何一个。为了防止对函数进行意外修改,成员方法被转换为 const。相反,constexpr 的目的是在构建时计算表达式,从而在执行代码时节省时间。Constexpr 可以与成员和非成员函数一起使用,包括构造函数,而 const 只能与非静态成员函数一起使用。然而,有一个要求是参数和返回类型必须是字面量类型。