C++ 11 中的 constexpr与const的区别

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

  1. 在 C++ 11 中,一个 constexpr 函数应该只包含一个 return 语句。C++ 14 允许多个语句。
  2. constexpr 函数应该只引用常量全局变量。
  3. constexpr 函数只能调用其他 constexpr 函数而不是简单函数。
  4. 该函数不应为 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 可以与成员函数和非成员函数一起使用,即使是构造函数,但条件是参数和返回类型必须是文字类型。