目录
前言
const作为我们学习编程中必不可少的关键字,用法也是非常的细节;constexpr的使用可能就比较小众,但技多不压身,友友我们一起来学习吧
const关键字
const可引用以下对象:
1.普通对象
2.const对象
3.临时对象(含有常性)
且const在使用引用和指针时是具有权限放大和缩小的特性的
引用的权限放大和缩小
接下来我们通过代码示例来向友友们讲解


如图,为const的权限放大的例子,定义变量a前加上const,则为只读;而下面的定义ra为a的别名,则将只读性质放大为可读可写,所以为权限放大,报错。


如图,为const的权限缩小处理,则正确,不会报错。
为了验证友友们是否真的学会了如何判断权限是放大还是缩小,以下是个很典型的例子

判断这个为权限的放大还是缩小?
答案是:既不是权限的放大也不是权限的缩小,这只是普通的拷贝赋值。简单的来说就是c赋值给了d,然后d和c所指的不是同一个空间。
临时对象
可能大家会有见过如下的代码


是不是感觉没问题的样子,或者感觉有问题但是不知道出在哪里?
但是这种写法是错误的,ra引用的不是a这个变量,而是a*3这个式子,然而这样的话编译器就会自动为你这个式子开辟一个临时对象,且这个ra是用来存储a*3结果的。临时对象是具有常性的,本质是权限的放大,然后加上const即可。

再来看第二个例子,相同的double定义的b变量,在进行向int引用的rb转换,在这两个变量之间会多出一个int临时对象然后进行存储转换,将b存进去进行转换,相同的rb引用的也是这个临时对象,并且临时对象是具有常性的,所以同样本质是权限的放大,在前面加上const即可。

值得注意的点:
大家平时写代码的时候总会有需要用到函数,这样的话就建议大家在所定义的形参前加上const,如下图所示。

加上const的好处:
1.如图中定义xx变量使用了 const引用定义,然后函数的形参加上了const可以直接进行调用xx,不然会存在权限放大的问题,产生报错。
2.普通变量a,函数的形参加上const也可以直接引用。
3.如图a*3这种带有常性的式子,同样也需要加上const来进行调用,不然会有权限放大的问题,对于权限放大不明白的友友可以去看看前面的例子讲解。
4.如图对double定义的变量b来进行传参,也同样需要加上const,因为double的b向int的rb进行转换中间需要有一个int的临时变量,临时变量具有常性,所以不加const会报错
还有一种情况(不需要加上const,但是会有局限性):

如图,这样直接用int对象不也行吗?当然可以,但是只能局限于我们当前这种很普通的函数,所需要的参数不是很大的情况,并且这样的传参方式的传值传参,遇到很大的参数传入效率就会大打折扣且代价很大,所以如果加上引用的话就会更好。如果想引入更多的对象来进行传参且不该表形参的变量,就得加上const。

不理解的友友可以再看下面这个例子

等到后面我们会接触到模板函数,如图T,可以为int,double等等类型,在形参处加上const,就会更好地避免权限放大等问题。
constexpr关键字
constexpr 关键字用于指明其后是一个常量(或者常量表达式,即值不会改变),编译器在编译程序时可以顺带将其结果计算出来,而无需等到程序运行阶段,这样的优化极大地提高了程序的执行效率。
编译器计算
constexpr int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
int main()
{
constexpr int n = factorial(10);
printf("%d\n", n);
}
总结
在 C++ 11 标准中,const 用于为修饰的变量添加"只读"属性;而 constexpr 关键字则用于指明其后是一个常量(或者常量表达式),编译器在编译程序时可以顺带将其结果计算出来,而无需等到程序运行阶段,这样的优化极大地提高了程序的执行效率。