const 限定符详解

背景

const 限定符的使用经常出现混淆,所以在此总结。

const 限定符与初始化

  1. const 对象
    const 对象一旦创建就不能改变,因此,必须初始化。
  • const 对象与初始化
  • 不改变const 对象的操作中有一种是初始化操作。//注解:改变const 对象的行为是会被拒绝的,但初始化操作是不在范围内的。
int i = 42 ; 
const int ci = i; // ture 
int j =  ci ; // ture
  1. const 与引用
  • 复合类型
  1. 引用与指针都是属于复合类型;

变量的定义 = 基本数据类型 + 声明符

  • const 的引用(reference to const)
const int ci = 1024;
const int &r1 = ci; // ture;
r1 = 42; //false,对常量的引用不能被用作修改他所绑定的对象
int &r2 = ci;// false,底层const的拷贝,只能从非const 拷贝到const;反之,则不行。
  • 引用的类型必须与其所引用的对象的类型一致,但是有个例外:初始化常量引用时,允许用任意表达式作为初始值;只要该表达式的结果能转化成引用的类型即可。
int i = 42;
const int &r1 = i; // ture 
const int &r2 = 42; // ture
const int &r3 = r1 * 2;// ture;
int &r4 = r1 * 2; // false ,r4是普通的非常量引用

实现基础:编译器将生成中间变量

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

生成中间的参量

const int temp = dval;
const int &ri = temp;

3.const 与指针

  • 指针
    指针是对象,存放的是对象的地址
  • 指向const 的指针(point to const)
    不能用于改变其所指对象的值
    想要存放常量对象的地址,必须使用指向常量的指针
const double pi = 3.14;
double *ptr = pi; // false,ptr只是一个普通指针
const double * cptr = pi; // ture
*cptr = 42;
  • const 指针
    指针是对象,因此可以把他定义为常量。
int errNumb = 0;
int *const curErr = &errNumb; // 不能改变所指对象
const double pi = 3.14;
const double *const pip = π //指向常量对象的常量指针;

4.常量指针和引用都可以指向非常量
5.顶层const 与底层const

  • 顶层const 表示任意对象是常量
  • 底层const 表示所指对象是const
int i = 0;
int *const p1 = &i; //顶层const;
const int ci= 42;
const int *p2 = &ci; //底层const,p2可以改变
const int *const p3 = p2; //右侧是顶层const,左侧是底层const
const int &r = ci; // 所有引用都是底层const;

6.对象执行拷贝工作时,顶层与底层const 差别很大。顶层基本不受影响,但底层与差别。

i = ci; // 顶层const 无影响
p2 = p3; // p2, p3 所指对象相同,忽略p3的顶层const 属性
  • 底层const 的受限比较多,所指对象必须一致,或者可以相互转化。一般来说,可将非常量转化成常量
int *p = p3; // false,p3包含底层const
p2 = p3; // ture;
p2 = &i; // ture, int * 转化成 const int *
int &r = ci; // false ,普通int 无法绑定到const int 
const int &r2 = i; // const int 可以绑定到 int ;
### 总结:
const 本质上是个常量的声明;因此常见的初始化语句(本质上都是拷贝语句)都可以忽略const,不管是作为左值还是右值;拷贝语句也可以忽略const;但是存在两种复杂的复合结构:指针和引用。他们所指的类型必须和其本身的类型一致或者可转化。

你可能感兴趣的:(const 限定符详解)