当前位置: 首页 > 最新文章 > 正文

C++ constexpr(c++ const constexpr)

C++11有许多改善特性,使得程序可以运行的更快。将构造函数声明为constexpr,允许他在编译器运行,前提是他只包含初始化列表,且初始化使用其他constexpr构造函数。constexpr 对比 const如果你将一个成员函数声明为constexpr,他也被认为是const的。constexpr和浮点数到目前为止,我们看到的constexpr功能都可以用模板元编程的方式实现。另外C++长期因

admin

C++11有许多改善特性,使得程序可以运行的更快。将构造函数声明为constexpr,允许他在编译器运行,前提是他只包含初始化列表,且初始化使用其他constexpr构造函数。constexpr 对比 const如果你将一个成员函数声明为constexpr,他也被认为是const的。constexpr和浮点数到目前为止,我们看到的constexpr功能都可以用模板元编程的方式实现。另外C++长期因相当长的编译期时耗而备受诟病;constexpr是个高效的工具,但是他另外引入了编译期时耗。因为constexpr函数可以被持久化,用constexpr替换模板元编程,性能上不会更糟糕,而且易读性更有提升。最后,C++11标准允许编译器限制constexpr函数的最大递归。这一约束,防止的极端情况下的严重性能损耗。

C++11有许多改善特性,使得程序可以运行的更快。其中之一就是常量表达式,令程序可以重复利用编译期计算。如果你熟悉模板元编程,常量表达式看起来像一种令你更方便工作的工具。如果你不熟悉模板元编程,没关系,常量表达式使得你更容易利用编译期计算能力。

常量表达式的基本思想是让确定可计算结果在编译期进行计算(就是代码被编译的时候),而不是程序运行的时候。这有一个明显的性能提升:如果一些工作可以在编译器完成,他只需要计算一次,而不是每次运行程序的过程中,都计算一次。假设我们需要计算特定值的sin或者cos,当然你可以使用库函数进行计算,但是你付出的代价就是,运行期函数调用。使用常量表达式,你可以创建一个函数,在编译期为你计算这个值。

基本使用方法

为了在编译期处理,你需要使用constexpr关键字:

C++11:常量表达式

常量表达式的另一大用处,你可以在原来使用的宏的地方,用这个函数代替。例如,你想要定义一个函数,基于一个乘子计算数组的长度。在之前的C++版本,你只能为此创建一个宏或者使用模板元编程的方式,因为不能使用函数调用的结果声明数组的长度。但是使用常亮表达式,你可以在数组声明的地方调用constexpr函数:

C++11:常量表达式

constexpr函数的限制

一个constexpr函数有一些非常严格的限制:

  • 只能由一个return语句组成(有几个例外)

  • 只能调用其他constexpr函数

  • 只能引用constexpr全局变量

注意,递归是没有被限制的。你如何在只由一个return语句组成的函数里使用递归呢?可以使用三元操作符(冒号问号操作符)。例如,下面是一个计算阶乘函数:

C++11:常量表达式

现在,你可以使用factorial(2),编译器在看到这个调用的时候,就会在编译期计算它。通过这种方式,constexpr可以进行更发杂的运算,constexpr函数表现的也跟纯粹的inline函数不一样,inline函数不允许递归!

  • constexpr函数中还可以做什么?

constexpr函数只能有一行可执行代码,但是它还可以包含别的内容:类型定义(typedef),using声明,指令(directive),静态断言(static_assert)。

constexpr和运行时

一个函数被constexpr修饰,它仍然可以在运行时被调用,此时函数参数不是常量:

C++11:常量表达式

这意味着,你不需要为编译期和运行时分别定义函数。

编译期对象

因为constexpr函数引用的任何变量都必须是constexpr的,那如何使用对象呢?例如,怎么使用一个圆对象?

C++11:常量表达式

然后你希望可以像下面那样编译器获得圆对象,并且计算它的面积:

C++11:常量表达式

实际上,仅仅需要对Circle类做一些简单的改动,你就可以这样做。首先,我们需要声明构造函数为constexpr,然后,我们需要声明getArea函数为constexpr。将构造函数声明为constexpr,允许他在编译器运行,前提是他只包含初始化列表,且初始化使用其他constexpr构造函数。

C++11:常量表达式

constexpr 对比 const

如果你将一个成员函数声明为constexpr,他也被认为是const的。(很明显,constexpr必定const,因为constexpr函数不能修改对象。)如果你将一个变量声明为constexpr,他也被认为是const的。但是反过来,都不成立。

constexpr和浮点数

到目前为止,我们看到的constexpr功能都可以用模板元编程的方式实现(虽然很麻烦)。但是,使用constexpr有一个全新的能力,编译期计算浮点数。因为,无类型参数模板不支持浮点数,你很难使用模板元编程的方法在编译期计算浮点数。

另外

C++长期因相当长的编译期时耗而备受诟病;constexpr是个高效的工具,但是他另外引入了编译期时耗。然而,有一些內建的特性可以优化这种时耗。首先,因为constexpr函数总是返回一样的输出值,他们可以被持久化,事实上GCC已经支持了memoization特性。

因为constexpr函数可以被持久化,用constexpr替换模板元编程,性能上不会更糟糕,而且易读性更有提升。再算上模板大量实例化的时耗的话,constexpr的性能反而更好。

最后,C++11标准允许编译器限制constexpr函数的最大递归(最少支持512层)。这一约束,防止的极端情况下的严重性能损耗。

C++11:常量表达式


上一篇: 教你编写一个手势解锁控件 下一篇:腾讯 QQ 安卓正式版 8.8.11 发布:全新简洁模式,视频通话新特效
返回顶部