const是一种限定符,被const所限定的变量其值不能够被改变。c++
因为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状况,即:code
咱们通常称符合第一种状况的为具备底层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。ci
上面提到,只有在等号右边和等号左边的类型具备相同的底层const属性,才能够进行赋值或者初始化。
然而有些时候等号右边可能并不具备和等号左边一致的底层const却依然能够成立,这是由于等号右边的类型发生了隐式转换从而具备了和等号左边类型相同底层const属性。
例如:get
int i=5; int *p=&i; const int *cp=p//int*隐式转换称为了const int*
为何int 转换成const int 被设定为合法的呢,由于在将int 转换为const int 的过程当中用户的权限变小了,在这一转换过程当中并不会使程序变得不可靠。
由此咱们能够得知非底层const的指针是能够经过隐式转换转变成底层const的。编译器
能够把引用绑定在const的变量上,称为const的引用,对常量的引用。
与普通的引用不一样的是,对常量的引用不能被用做修改它所绑定的对象编译
const int ci=5; const int &r=ci; r=6//错误不能够经过常引用来修改值 int &r2=ci//错误,试图让一个很是量引用指向一个常量对象。
咱们知道对于引用来讲初始化时必定要用一个对象初始化,且该对象的类型须要与之匹配。
可是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++程序员们经常把临时量对象简称为临时量。
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。