好久没有更新博客了,与最近考试多有关,也与个人怠惰有关

今天的内容是指向常量的指针(pointer to const)与指针常量(const pointer),这是昨天在阅读《c++ primer》中重新理解的内容,有了些许新的感悟,趁热打铁,发在博客上

在讲那两个之前,先说一下const与对常量的引用(reference to const)

const修饰词

使用const修饰词修饰的变量,即常量,是必须初始化的,且初始化后不能修改其值

初始化时除了用如下方法

1
const int a=1;

同样可以用非常量但同类型的值进行赋值(拷贝)

1
2
3
int a=1;
const int b=a;
a=b;

const修饰的对象在编译时直接替换,类似define,即提前将所有出现其的位置替换成对应的数值,不申请额外空间

以下场景除外(都要等具体的值才能初始化)

1
2
const int a =fun();
const int &b=c;

同时const对象仅在文件内部有效,要实现在一个文件中定义,在多个文件中声明并使用,要用extern 关键字修饰所有const对象

对const的引用(常量引用)

1
2
3
4
5
6
常量引用本身是常量,无法修改引用的对象
const int a=1;
const int b=2;
const int &r =a;
r=b;//错误,不可修改
r=2;//错误,不可修改

常量引用不能改变引用的值(毕竟常量的值无法改变)

要对常量使用引用,也只能使用常量引用

但是,常量引用可以引用非常量的同类型变量

1
2
3
4
5
6
int i=0;
const int &r =i;//正确

const int &r2=r1*2;//正确

i=4;//i不是常量,可以修改,同样会导致r的值变动

这种场景经常出现,甚至比引用常量更多,主要应用场景在函数参数传递时,传递参数的常量引用,可以确保参数不被修改,同时避免拷贝的花销。

在接口等地方非常常见,可以参考《effective c++》中的建议

可以理解为常量引用引用的是一个临时常量,变量的值赋给了临时变量。

ok.到此为止,下面是指向常量的指针与常量指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int a = 1;
int b = 2;

常量指针
int* const p1 = &a;
*p1 = 6;
// const pointer,本身是个常量,不能改变指向的对象
//只能指向变量,无法指向常量
//如果指向的对象并非是常量,指向对象的值还是可以修改的

指向常量的指针
const int* p2 = &a;
p2 = &b;//正确,pointer to const,本身不是常量,可以改变指向的对象
*p2=3;//错误,无法通过这种方式修改指向的变量的值
//类似常量引用,可以指向常量,也可以指向变量

const int* const p3 = &a;//指向常量的常量指针

顶层const与底层const

顶层const表示其本身是常量,即常量和常量指针,无法修改其值(常量指针无法修改指向的对象,即地址,也就是其值)

底层const表示指向(引用)的对象是一个“常量”(常量或变量),无法修改指向(引用)对象的值,即常量引用和指向常量的指针等

拷贝时,两者区别非常明显

顶层const,可以随意赋给变量做值

底层const,不可以赋给变量做值

1
2
3
4
5
6
int a=1;
const int *r1=a;
int *const r2=a;

int *p=r1;//错误,底层const无法赋值
int *p=r2;//正确