IT教程 ·

[C/C++]const限定符总结

const限制符

const是一种限制符,被const所限制的变量其值不能够被转变。

const的初始化

由于const一旦建立其值就不能够被转变,所以我们必需对其举行初始化

const int a;//毛病,const变量必需举行初始化!
const int b=10;//准确,编译时初始化
const int c=get_size();//准确,运行时初始化

雷同范例的变量互相初始化时,不管变量是不是被const限制我们都能够举行随便的互相拷贝。由于在拷贝过程当中我们只会用到等式右侧变量的右值属性,不必在乎其是不是能够转变。

int m = 5;
const int n = m;
int j = n;

const与指针

顶层const与底层const

关于指针来讲,由于其指向另一片内存的特征,有三种差别的const状况,即:

  1. 指向常量的指针(const int *)
  2. 常量指针(int * const)
  3. 指向常量的常量指针(const int *const)

我们平常称相符第一种状况的为具有底层const属性。
相符第二种状况的为具有顶层const属性。
第三种状况兼而有之。

关于带有const的指针的互相赋值(或许初始化)问题

  1. 顶层const并不会影响变量间的互相拷贝(缘由是顶层const只保证自身的值不会转变,const没有转变自身的变量范例,在拷贝时只是运用该范例的右值)。
  2. 假如等号右侧是底层const,那末等号左侧必需保证为雷同的底层const(或许等号右侧的范例能够转换成等号左侧的范例),否者表达式没法经由过程编译。

关于底层与顶层const的一些主意

const的底层与顶层属性好像只在指针上存在。然则c++primer中有如许的代码和解释:

const int ci=1,&cr=ci;
auto b=ci;//b是一个整数(ci的顶层const特征被疏忽掉了)
auto c=cr;//c是一个整数(cr是ci的别号,ci自身是一个顶层const)

这段代码是为了申明auto申明符平常会疏忽掉顶层const的特征,在解释中明白写着ci自身是一个顶层const
这也与我的观点一致,底层与顶层const实际上并非指针所特有的,只如果不能转变对象自身的对象都具有顶层const,而不能转变本身所指向的对象的对象都具有底层const。
从这个角度看,援用实际上自带顶层const。

底层const的隐式转换

上面提到,只需在等号右侧和等号左侧的范例具有雷同的底层const属性,才能够举行赋值或许初始化。
但是有些时刻等号右侧大概并不具有和等号左侧一致的底层const却依旧能够建立,这是由于等号右侧的范例发生了隐式转换从而具有了和等号左侧范例雷同底层const属性。
比方:

int i=5;
int *p=&i;
const int *cp=p//int*隐式转换称为了const int*

为何int 转换成const int 被设定为正当的呢,由于在将int 转换为const int 的过程当中用户的权限变小了,在这一转换过程当中并不会使程序变得不可靠。
由此我们能够得知非底层const的指针是能够经由过程隐式转换转变成底层const的。

const与援用

能够把援用绑定在const的变量上,称为const的援用,对常量的援用。
与一般的援用差别的是,对常量的援用不能被用作修正它所绑定的对象

const int ci=5;
const int &r=ci;
r=6//毛病不能够经由过程常援用来修正值
int &r2=ci//毛病,试图让一个非常量援用指向一个常量对象。

const援用的初始化

我们晓得关于援用来讲初始化时肯定要用一个对象初始化,且该对象的范例须要与之婚配。
然则const的援用是个破例,在初始化常量援用时许可用恣意表达式作为初始值,只需该表达式的效果能转换成援用的范例即可,以至许可为一个常量援用绑定非常量的对象、字面值或许是表达式。

int i=42;
const int &r1=i;//许可将const int&绑定到一个一般int对象上
const int &r2=3.14;//准确:r2是一个常量援用
const int &r3=r1*2;//准确:r3是一个常量援用
int &r4 =r1*2;//毛病,非常量援用不能用表达式初始化。

C++primer中给出了能够这么做的缘由:

要想明白这类破例状况的缘由,最简朴的要领是弄清楚当一个常量援用被绑定到别的一种范例上都时究竟发生了什么:

double dval=3.14;
const int &ri=dval;

此处ri援用了一个int型的数。对ri的操纵应该是整数运算,但dval倒是一个双精度浮点数而非整数。因而为了确保让ri绑定一个整数,编译器把上述代码变成了以下情势:

const int temp=dval;//由双精度浮点数生成一个暂时的整型常量
const int &ri=temp;//让ri绑定这个暂时量

在这类状况下,ri绑定了一个暂时量对象。所谓暂时量对象就是当编译器须要一个空间来暂存表达式的求值效果时暂时建立的一个未命名的对象。C++程序员们经常把暂时量对象简称为暂时量。

const与auto范例申明符

auto范例申明符是C++11中新引入的范例申明符,能够自动揣摸范例。
编译器揣摸出来的auto范例有时刻和初始值的范例并不完整一样,编译器会恰当的转变效果范例使其更相符初始化划定规矩。
auto在揣摸带有const的对象时,编译器平常会疏忽掉顶层const,同时底层const则会保存下来。
别的关于援用由于援用没有真正的实体,所以假如用一个援用来初始化auto范例时,auto实际上为援用所指向的对象的范例,而非援用,假如要申明其为援用范例,须要运用auto&。

const int ci=i,&cr=ci;
auto b=ci;//b是一个整数(ci的顶层const特征被疏忽掉了)
auto c=cr;//c是一个整数(cr是ci的别号,ci自身是一个顶层const)
auto d=&i;//d是一个整型指针(整数的地点就是指向整数的指针)
auto e=&ci;//e是一个指向整数常量的指针(对常量对象取地点是一种底层const)

假如愿望揣摸出的auto范例是一个顶层const,须要明白指出:

const auto f=ci;//ci的推演范例为int,f是const int。

参与评论