const int bufSize = 512; //正确
const int bufSize2; //错误,const对象必须要初始化
int buffer[bufSize];
const int a = 1;
int b = 2;
a = 3; //错误,不能对常量进行赋值
b = a; //正确
//非常量引用
int a = 0;
int &r = a;
r = 1; //通过操作引用来对a赋值,此时相当于a=1
//常量引用绑定常量
const int b = 1; //b是一个常量
const int &r2 = b; //正确
r2 = 5; //错误,不能对常量引用进行修改
b = 5; //错误
//常量引用绑定变量
int c = 1;
const int &r3 = c; //正确,常量引用也可以绑定变量
r3 = 5; //错误,不可修改常量引用
int d = r3; //正确,常量引用可读,该值为c
c = 5; //正确,可修改变量
//非常量引用不可绑定常量
const int e = 1;
int &r4 = e; //错误
//1、常量指针
//常量指针指向变量,即常量指针中的地址不能修改
int a = 1;
int b = 2;
int *const p = &a; //正确,常量指针可以指向变量
p = &b; //错误,常量指针中的地址值不能修改
*p = 2; //正确,p的解引用是a的值,a是变量,可以修改该值
//2、指向常量的指针
//即指针中的地址可以修改,但指向的对象是常量不能用解引用修改值(实际上指向的对象可以是变量)
int c = 3;
const int d = 4;
int e = 5;
const int f = 6;
int const *p2 = &c; //正确,指向常量的指针可以指向变量
const int *p3 = &d; //正确,指向常量的指针指向常量
p2 = &e; //正确,可以改变指向的地址
p3 = &f; //正确
*p2 = 0; //错误,虽然p2实际指向的是一个变量,但操作p2的解引用时p2把指向的对象看作常量,因此不能通过解引用来修改对象的值
c = 0; //正确,不能通过p2的解引用修改c,但c自身是变量可以修改
*p3 = 0; //错误,同理p2
f = 0; //错误
//3、指向常量的常量指针
//即指针中的地址不可以修改,指向的对象是常量也不能用解引用修改值(实际上指向的对象可以是变量)
int g = 1;
const int h = 2;
const int *const p4 = &g; //正确
const int *const p5 = &h; //正确
p4 = &h; //错误,不能修改值
*p4 = 0; //错误,不能修改其解引用
int a = 0;
int const *p = &a; //底层const
const int &r = a; //底层const
很多朋友可能分不清一个指针到底是底层const还是顶层const,这里可以教大家一个方法,就是看变量名最近的声明符是什么,例如const int *p,最近的声明符是*,因此他是一个指针,第二个声明符才是const,因此他是一个指向常量的指针;又例如int *const p2,最近的声明符是const,因此p2是一个常量,第二个声明符才是*,因此它是一个常量指针。其实大家只要记住一个就行,各人有各人的方法,最紧要自己觉得好用啦。
了解了底层const,那么我们分析一下底层const可以进行哪些操作,以下为代码。
int a = 0;
const int b = 0;
int const *p = &a; //底层const可以指向常量也可以指向变量,因为对于&a该类型可以从int*转换为const int*,因此可以说成对象被拷贝时可以忽略其顶层const
//对于引用的底层const,即是常量引用
const int &r = a; //绑定一个变量
r = 0; //错误,引用的底层const不可以修改值。
int c = r; //正确
const int d = r; //正确
int &r2 = r; //错误
const int r3 = r; //正确
//对于指针的底层const,即指向常量的指针
//修改指针的值
p = &b; //正确,指针的底层const可以修改值
*p = 2; //错误,指针的底层const不可以修改解引用的值
//指针被拷贝
int *p2 = p; //错误
int *const p3 = p; //错误
int const *p4 = p; //正确
const int *const p5 = p; //正确,p5有顶层和底层const