constexpr是 C++ 11 中添加的一项功能。主要思想是通过在编译时而不是运行时进行计算来提高程序的性能。请注意,一旦开发人员编译并最终确定了程序,用户就会多次运行它。这个想法是在编译上花费时间并在运行时节省时间(类似于模板元编程)。constexpr 指定可以在编译时计算对象或函数的值,并且该表达式可以在其他常量表达式中使用。
例子:
// C++ program to demonstrate constexpr function for product
// of two numbers. By specifying constexpr, we suggest
// compiler to to evaluate value at compile time
#include <iostream>
constexpr int product(int x, int y) { return (x * y); }
int main()
{
constexpr int x = product(10, 20);
std::cout << x;
return 0;
}
输出
200
一个函数被声明为 constexpr
- 在 C++ 11 中,一个 constexpr 函数应该只包含一个 return 语句。C++ 14 允许多个语句。
- constexpr 函数应该只引用常量全局变量。
- constexpr 函数只能调用其他 constexpr 函数而不是简单函数。
- 该函数不应为 void 类型,并且在 constexpr 函数中不允许使用某些运算符,如前缀增量 (++v)。
constexpr 与内联函数
概念 | 内联函数 |
---|---|
它在编译时评估代码/表达式时删除了函数调用。 | 它几乎不删除任何函数调用,因为它在运行时对表达式执行操作。 |
可以在编译时评估变量或函数的值。 | 无法在编译时评估函数或变量的值。 |
它并不意味着外部联系。 | 它意味着外部联系。 |
constexpr 的性能改进示例:
// A C++ program to demonstrate the use of constexpr
#include<iostream>
constexpr long int fib(int n)
{
return (n <= 1) ? n : fib(n-1) + fib(n-2);
}
int main ()
{
// value of res is computed at compile time.
constexpr long int res = fib(30);
std::cout << res;
return 0;
}
输出
832040
当上面的程序在 GCC 上运行时,它需要0.003 秒(我们可以使用time 命令测量时间)如果我们从下面的行中删除 const,那么 fib(5) 的值不会在编译时计算,因为constexpr 的结果未在 const 表达式中使用。
Change,
constexpr long int res = fib(30);
To,
long int res = fib(30);
进行上述更改后,程序花费的时间增加了0.017 秒。
带有构造函数的 constexpr:使用 constexpr 说明符声明的构造函数是 constexpr 构造函数,也可以将 constexpr 用于构造构造函数和对象。constexpr 构造函数是隐式内联的。
可以使用 constexpr 的构造函数的限制:
- 没有虚拟基类
- 每个参数都应该是字面量
- 它不是一个 try 块函数
例子:
// C++ program to demonstrate uses
// of constexpr in constructor
#include <iostream>
// A class with constexpr
// constructor and function
class Rectangle
{
int _h, _w;
public:
// A constexpr constructor
constexpr Rectangle(int h, int w) : _h(h), _w(w) {}
constexpr int getArea() { return _h * _w; }
};
// driver program to test function
int main()
{
// Below object is initialized at compile time
constexpr Rectangle obj(10, 20);
std::cout << obj.getArea();
return 0;
}
输出
200
constexpr 与 const
它们服务于不同的目的。constexpr 主要用于优化,而 const 实际上用于 const 对象,例如 Pi 的值。它们都可以应用于成员方法。将成员方法设为 const 以确保方法中没有意外更改。另一方面,使用 constexpr 的想法是在编译时计算表达式,以便在运行代码时节省时间。const 只能与非静态成员函数一起使用,而 constexpr 可以与成员函数和非成员函数一起使用,即使是构造函数,但条件是参数和返回类型必须是文字类型。