常量对象(const 对象):
在定义对象的基本数据类型前加上 const 关键字就声明了一个const 对象,const 对象与非const 对象的主要区别就在于 只能在const对象上执行不改变其内容的操作!!! 并且const对象一旦创建后其值不可被改变,因此const对象必须初始化!
例子如下:
const int i; //错误, const对象必须初始化
const int i = 512; //正确
i = 512; //错误,const对象一旦被创建就不可在被赋值
常量引用(const 引用):
把引用绑定到const对象上就是常量引用,但对常量的引用不能被用作修改它所绑定的对象,即无法通过常量引用修改对象值,但是通过其他方式修改对象的值也可以改变const引用的值,并且const对象只能被绑定到const引用上,但是const引用可引用一个非const 对象。
例子如下:
const int i = 512;
const int &j = i; //正确,引用及其对象都是常量
int &k = i; //错误,k不是一个const引用,不能引用const对象
int m = 512;
const &n = m; //正确, const引用可以与非const对象绑定
double x= 3.14
const int &y = x; //正确,常量引用可以绑定到另外一种类型的对象上
int i = 42;
const int & r2 = i;
cout << "r2:" << r2 << '\n'; // r2为42
r2 = 10; //错误,r2是一个常量引用不能修改对象值
i = 10;
cout << "i:" << i << '\n'; //对象i的值被修改
cout << "r2:" << r2 << endl; //由于r2与对象i绑定在一起,所以r2的值也被修改为10
const i = 42; //如果i是一个常量对象,则无法被修改了
指向常量的指针
与引用类似,也可以令指针指向常量或者非常量,指向常量的指针不能修改其所指对象的值,并且只有指向常量的指针才能存放常量对象的地址,但是指向常量的指针也可以存放非常量对象的地址
例子如下:
const double pi = 3.14;
double *ptr = π //错误,ptr只是一个普通指针
const double *cptr = &pi //正确,ptr是一个指向常量对象的指针!
*cptr = 42; //错误,指向常量的指针不能修改其所指对象的值!
double k = 1.0;
const double *cptr = &k //正确,ptr也可以指向非常量对象
常量指针(const 指针)
首先需要清楚指针与对象的区别:
引用本身并不是对象,引用就是给已经存在的对象起另外一个名字;但是指针本身就是一个对象,允许对指针进行赋值和拷贝
所以指针本身也是一个对象,也可以被限定为常量对象->即常量指针,所以常量指针的地址不能被改变(this指针就是一个常量指针),但是常量指针所指对象的值可以被改变。
例子如下:
int errNumb = 0;
int *const curErr = &errNumb; //curErr是一个常量指针,将一直指向errNumb所在的地址
curErr = 0; //错误,curErr是一个常量指针,其所指向的地址不可被改写
*curErr = 1; //正确,curErr所指对象的内容可以被改写!
指向常量的常量指针
常量指针必须初始化,且一旦初始化完成,其指向的地址值便不可再修改!!!
如下例子中,对于定义的pip,可以从右向左阅读:首先离pip最近的是const,表明pip是一个常量对象,紧接着声明符的下一个符号是*,表明pip是一个常量指针;之后的double表明pip指向的是一个double对象,而double之前的一个const则表明该对象是一个常量对象。所以我们无法修改pip指针指向的地址,也无法通过pip指针修改其指向对象的值
const double pi = 3.14;
const double *const pip = π
pi = 4.1; //由于Pi是常量对象,所以其值不允许被修改
double pi = 3.14;
const double *const pip = π
*pip = 4.1; //无法通过pip指针修改所值对象的值
pi = 4.1; //Pi不是常量对象,所以其值允许被修改
cout << *pip; //并且此时pip指针指向的值也被修改为4.1