本文是C++11新特性介绍的第十八部分,涉及到constexpr相关的新特性。
语义上的差别
首先,我们来看看《C++Primer》怎么说的:
const:有时我们希望定义这样一种变量,它的值不能被改变。例如,用一个变量来表示缓冲区的大小。使用变量的好处是当我们觉得缓冲区大小不再合适时,很容易对其进行调整。另一方面,也应随时警惕防止程序一不小心改变了这个值。为了满足这一要求,可以用关键字const对变量类型加以限定。
constexpr(常量表达式):是指值不会改变并且在编译过程就能得到计算结果的表达式。
从以上两段话,我们可以总结出const和constexpr的关系,即如果变量用constexpr修饰,那么变量也具有const的特性;如果变量用const修饰,不能说明变量具有constexpr的特性。
从语义上讲,const更像是“read only”,而constexpr更像是“const”。
接下来,我们来聊一聊为什么要引入constexpr?
常量表达式的优势
常量表达式的优点是将计算过程转移到编译时期,那么运行期就不再需要计算了,程序性能也就提升了。
const时期的常量表达式
一个对象(或表达式)是不是常量表达式由它的数据类型和初始化值共同决定的,例:
其中d不是常量表达式的原因是,尽管d本身是一个常量,但它具体的值需要在运行期才能获得,所以不是常量表达式。
第四句代码就是我们常常说的“伪优化”,误以为这段热点语句已经改成了常量表达式,性能将会有所提升,但其实,并没有啊……
constexpr时期的常量表达式
为了能明确的表示这段代码一定是常量表达式,在C++11中,引入了constexpr,有了它,我们来看看abcd四个变量的变化:
其中变量d有两种情况:
(1)当getlength()函数也是constexpr时,那么d就是常量表达式
(2)当getlength()函数不是constexpr时,此时编译会报错。
即编译器帮助我们检查了常量表达式。
所以,一般来说,当你认为变量一定是常量表达式,那就把它声明成constexpr类型吧。
实测下的性能差别
为了让大家更加直观的感受常量表达式和普通表达式的性能差别,请看以下代码:
这段代码比较简单,一个常量表达式和一个非常量表达式,都进行相同的计算,都循环10w次,然后记录各自的总耗时,单位是微秒。
打印结果如下:
大家可以看到,接近5倍的性能差别,这要是发生在高性能开发中,将是一次不错的性能提升。