C++中关于const和constexpr的用法
1.const关键字
常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。不管出现在任何上下文都是为这个目的而服务的。
-
const类型的变量必须在声明的时候就要去初始化。
-
const类型的变量一旦初始化后就不能被修改。
-
对于类中的const成员变量必须通过初始化列表进行初始化,如下所示:
-
在全局作用域里定义非const变量时,它在整个程序中都可以访问。我们可以把一个非const变量定义在一个文件中,假设已经做了合适的声明,就可以在另外的文件中使用这个变量
与其他变量不同,除非特别说明,在全局作用域声明的const变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定const变量为extern,就可以在整个程序中访问const对象。
注意:非const变量默认为extern。要使const变量能够在其他文件中访问,必须在文件中显式地指定它为extern。
2.constexpr的使用
C++11为了提高代码执行效率做了一些改善。这种改善之一就是:生成常量表达式,允许程序利用编译时的计算能力。假如你熟悉模板元编程,你将发现constexpr使这一切变得更加简单。constexpr使我们很容易利用上编译时编程的优势。
常量表达式主要是允许一些计算发生在编译时,即发生在代码编译而不是运行的时候。这是很大的优化:假如有些事情可以在编译时做,它将只做一次,而不是每次程序运行时。需要计算一个编译时已知的常量,比如特定值的sine或cosin?确实你亦可以使用库函数sin或cos,但那样你必须花费运行时的开销。使用constexpr,你可以创建一个编译时的函数,它将为你计算出你需要的数值,用户的电脑将不需要做这些工作。
3.const与constexpr的区别
const其实不能表示“常量”,它只是一个对变量的修饰,告诉编译器这个变量只能被初始化,且不能被直接修改。而这个变量,可以在编译的时候初始化,也可以在运行的时候初始化。
constexpr可以用来修饰变量,函数,构造函数。一旦以上任何元素被constexpr修饰,那么等于告诉编译器“请大胆地将我看成编译时就能得出常量值的表达式去优化我”。
下面我们来看一下下面两个代码,可能能更好的理解上面说的区别。
- 下面这个代码是完全可以编译通过的,因为这种办法是并没有限制数组a的大小,数组a的大小还是由后面的初始化来决定的。而且数组的大小必须是一个常量表达式
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int p(){ // 这里用const修饰函数,加不加没有区别
return 2;
}
int main(){
const int a[p()]={1,2,3};
for(int i=0;i<3;i++){
printf("%d ",a[i]);
}
return 0;
}
- 而下面这个代码在编译的时候就会报错,因为constexpr告诉了编译器我在编译的时候在就要初始化,因此函数在编译的时候发现 a[ 2 ] = { 1,2,3 },发生了数组越界。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
constexpr int p(){
return 2;
}
int main(){
const int a[p()]={1,2,3};
for(int i=0;i<3;i++){
printf("%d ",a[i]);
}
return 0;
}
- 下面这个例子就说明了const可以在运行时初始化,而constexpr只能在编译时初始化。两者都不能修改。