C++11之常量表达式
2016-10-14 23:22
155 查看
C++11系列-常量表达式
2013-09-17C++11有一些这样的改善,这种改善保证写出的代码比以往任何时候的执行效率都要好。这种改善之一就是生成常量表达式,允许程序利用编译时的计算能力。假如你熟悉模板元编程,你将发现constexpr使这一切变得更加简单。假如你不知道模板元编程,也没什么。constexpr使我们很容易利用上编译时编程的优势。
常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候。这是很大的优化:假如有些事情可以在编译时做,它将只做一次,而不是每次程序运行时。需要计算一个编译时已知的常量,比如特定值的sine或cosin?确实你亦可以使用库函数sin或cos,但那样你必须花费运行时的开销。使用constexpr,你可以创建一个编译时的函数,它将为你计算出你需要的数值。用户的电脑将不需要做这些工作。
constexpr初探
为了使函数获取编译时计算的能力,你必须指定constexpr关键字到这个函数。constexpr int multiply (int x, int y) { return x * y; } // 将在编译时计算 const int val = multiply( 10, 10 ); |
constexpr int getDefaultArraySize (int multiplier) { return 10 * multiplier; } int my_array[ getDefaultArraySize( 3 ) ]; |
constexpr函数的限制
一个constexpr有一些必须遵循的严格要求:函数中只能有一个return语句(有极少特例)
只能调用其它constexpr函数
只能使用全局constexpr变量
注意递归并不受限制。但只允许一个返回语句,那如何实现递归呢?可以使用三元运算符(?:)。例如,计算n的阶乘:
constexpr int factorial (int n) { return n > 0 ? n * factorial( n - 1 ) : 1; } |
constexpr函数还有那些特点?
一个constexpr函数,只允许包含一行可执行代码。但允许包含typedefs、 using declaration && directives、静态断言等。
constexpr和运行时
一个声明为constexpr的函数同样可以在运行时被调用,当这个函数的参数是非常量的:int n; cin >> n; factorial( n ); |
编译时使用对象
假如你有一个Circle类:class Circle { public: Circle (int x, int y, int radius) : _x( x ), _y( y ), _radius( radius ) {} double getArea () const { return _radius * _radius * 3.1415926; } private: int _x; int _y; int _radius; }; |
constexpr Circle c( 0, 0, 10 ); constexpr double area = c.getArea(); |
class Circle { public: constexpr Circle (int x, int y, int radius) : _x( x ), _y( y ), _radius( radius ) {} constexpr double getArea () { return _radius * _radius * 3.1415926; } private: int _x; int _y; int _radius; }; |
constexpr vs const
假如你将一个成员函数标记为constexpr,则顺带也将它标记为了const。如果你将一个变量标记为constexpr,则同样它是const的。但相反并不成立,一个const的变量或函数,并不是constexpr的。
constexpr和浮点数
到这里我们讲到的constexpr功能都可以通过模板元编程实现。但constexpr支持的一项能力是可以计算浮点型的数据。因为double和float不是有效的模板参数,你不可以轻易的通过模板编译期计算浮点数的值。而constexpr允许编译期计算浮点型数据。
权衡constexpr
C++开发者早就深受修改一个头文件则引发重新编译导致编译缓慢的困扰。而constexpr可能引入增加编译时间的风险,但也有一些技术去降低这种风险。首先,因为constexpr函数相同的参数会输出相同的结果,所以它们可以被memoized,事实上GCC已经支持memoization。因为可以对constexpr函数memoize,所以用constexpr函数替换模板函数的地方,(编译)性能不会变得更坏,但代码会变得清晰。事实上,替换掉一部分模板实例,编译会显著加快。
最后,标准允许编译器去限制递归函数的级数。这样可以限制深度递归的编译性能损耗。
编译器支持
constexpr需要编译器支持编译期的递归,所以也不奇怪支持constexpr的编译器并不多,就我所知只有G++4.7支持这一特性。[注:到我翻译时,intelC++13、Clang3.1也都支持了,不过Vs2013还是不支持]来源:http://towriting.com/blog/2013/09/17/constexpr/
PS:常量表达式解决了数组无法使用函数返回值定义大小的问题。
相关文章推荐
- C++11系列-常量表达式
- C++11:常量表达式
- C++11系列-常量表达式
- C++11系列-常量表达式
- 【C++11】新特性——常量表达式constexpr
- constexpr与常量表达式(c++11标准)
- C++11常量表达式
- C++11 FAQ中文版:常量表达式(constexpr)
- C++11特性(11):常量表达式(值)
- C++11系列-常量表达式
- C++11 常量表达式
- c++11 常量表达式
- C++11系列-常量表达式
- c++11 constexpr常量表达式
- C++11 FAQ中文版:常量表达式(constexpr)
- C++11 新特性:Lambda 表达式
- sun的java编译器对string常量表达式的处理和优化
- RDLC 报表参数、常量及常用表达式的使用方法
- c++11标准:匿名函数(匿名表达式)lambda
- C++11 Lambda表达式