const 是 constant 的缩写,本意是不变的,不易改变的意思。在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。

C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。

1. const修饰普通类型变量

1
2
3
4
5
const int a = 7;	//编译时初始化
const int i = get_size(); //正确,运行时初始化
int b = a; //正确
a = 12; //错误,不可修改
const int c; //错误,const定义必须初始化

默认情况下,const对象尽在文件中有效;

如果想在多个文件中共享const对象,必须在变量的定义之前条件extern关键字;

1
2
3
4
//file1
extern const int bufSize = func();
//file2
extern const int bufSize;

2. const的引用

可以将引用绑定在const对象上,就像绑定在其他对象上一样,称之为对常量的引用(reference to const)。和普通引用不同,对常量的引用不能被用作修改他所绑定的对象;

1
2
3
4
const int ci = 1024;
const int &r1 = ci; //正确
r1 = 42; //错误
int &r2 = ci; //错误,试图让一个非常量引用指向一个常量对象

对const的引用可能引用一个并非const的对象

1
2
3
4
5
int i = 42;
int &r1 = i;
const int &r2 = i;

i = 32; //正确赋值,此时r2也随之改变为32;

上述表示不允许通过r2来修改i的值,但是i的值仍可以通过其他途径进行修改。

3. 指针和const

const修饰指针变量有以下三种情况。

  • A: const修饰指针指向的内容,则内容为不可变量。
  • B: const修饰指针,则指针为不可变量。
  • C: const修饰指针和指针指向的内容,则指针和指针指向的内容都为不可变量。

如同引用,可以令指针指向常量和非常量,类似于常量引用,指向常量的指针(pointer to const)不能用于改变其所指对象的值。

1
2
3
4
5
6
7
8
const double pi = 3.14;
double *ptr = π //错误,ptr是一个普通指针
const double *cptr = π //正确
*cptr = 42; //错误

double dval = 3.21; //
const double *cptr = &dval; //正确
dval = 3.14; //正确,*cptr也修改

则指针指向的内容不可改变。简称左定值,因为 const 位于 * 号的左边。

const指针

指针是对象而引用不是,因此可以向其他对象一样,允许将指针本身定为常量。const指针(const pointer)必须初始化,而且一旦初始化完成后,则该指针的值(存放在指针中的地址)就不能再改变了。把*放在const关键字之前用于说明指针是一个常量,即不变的是指针本身的值而非指向的那个值。

1
2
3
4
5
6
int errNumb = 0;
int *const curErr = &errNumb; //curErr一直指向errNumb

*curErr = 1; //正确
double newErr = 13;
curErr = &newErr; //不正确

对于 const 指针其指向的内存地址不能够被改变,但其内容可以改变。简称,右定向。因为 const 位于 * 号的右边。

第三种情况就是前两者的结合:

1
2
const double pi = 3.14;
const double *const pip = π //pip是一个指向常量对象的常量指针。

这时,const指针的指向的内容和指向的内存地址都已固定,不可改变。

4. 顶层const与底层const

  • 顶层const:表示任意对象本身就是一个常量;
  • 底层const:与指针和引用等复合类型的基本类型部分有关,如指针所指对象是一个常量;
1
2
3
4
int i = 0;
int *const p1 = &i //不能改变p1本身的值,这是一个顶层const
const int ci = 42; //不能改变ci的值,这是一个顶层const
const int *p2 = &ci; //不能改变p2的值,这是一个底层const

未完待续