文章目录
前言
本文主要记录const限定符在C++中的定义、使用及注意事项
一、const是什么?
const是C++中关键字,用于修饰变量与函数。对于修饰普通变量,const用于限定对变量本身的操作;对于修饰复合类型变量(引用、指针),const还可以限定对变量引用或指向的对象的操作;
二、使用与注意事项
1. 修饰变量
1.1 const与初始化
因为const对象一旦创建后其值就不能在改变,所以const对象必须初始化。
代码如下(示例):
const int i = 20; // 正确:编译时初始化
const int j; // 错误:未初始化
1.2 默认情况下,const变量仅在文件内有效
对于非const变量,由于它具有external特性,所以可以不在在变量的定义之前添加extern关键字;而const变量默认情况下,仅在文件内有效,所以,如果想要在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
代码如下(示例):
// file1.cpp定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufferSize = function();
// file1.h头文件
extern const int bufferSize; // 与file1.cpp中定义的是同一个
1.3 对常量的引用(reference to const)
形式(举例):const int &
字面含义:把引用绑定到常量对象上
解释:除了可以将该引用绑定到常量上,还可以将该引用绑定到非常量上。对常量的引用,只不过是引用的“自以为是”,它们觉得自己引用了常量,所以自觉地不去改变所引用对象的值(在编译期检测出来)。
const int ci = 10;
const int &r1 = ci; // 将引用绑定到常量对象上
int i = 20;
const int &r2 = i; // 将引用绑定到非常量对象上
r2 = 10; // 编译器认为r2引用的对象是常量,不可以改变所引用的对象的值,所以编译期间报错
1.4 常量与指针
1.4.1 指向常量的指针(pointer to const)
形式(举例):const int *
字面含义:指向常量的指针
解释:除了可以指向常量,还可以指向非常量。所谓指向常量的指针,只不过是指针的“自以为是”,它们觉得自己指向了常量,所以自觉地不去改变所指向的对象的值(在编译期检测出来)。
const int ci = 10;
const int *p1 = &ci; // 指向常量
int i = 20;
const int *p2 = &i; // 指向非常量
*p2 = 10; // 编译器认为p2指向的对象是常量,不可以通过解引用的方式去改变指向对象的值,所以编译期间报错
1.4.2 常量指针
指针是对象而引用不是,所以可以将指针本身定为常量。常量指针必须初始化。
形式(举例):int * const p;
解释:仅仅定义了指针本身不可被修改,与指针指向的对象不能被修改无关。要想指向的对象不被改变,就要设计将指针指向的类型为常量,即使用1.4.1节讲到的指向常量的指针,不过,这也仅仅只能在编译期间起限制作用。
1.5 顶层const
如前面所述,指针本身是一个对象,它又可以指向另一个对象。因此,指针本身是不是常量与指针所指的是不是常量是两个独立的问题。用名词顶层const表示指针本身是个常量,而用名词底层const表示指针所指的对象是一个常量。
顶层const可以表示任意的对象是常量。底层const则与指针和引用等复合类型的基本类型部分有关。由于引用不是对象,所以对常量的引用(reference to const)不是顶层const,而是底层const。
int i = 0;
int *const p1 = &1; // 常量指针,指针本身是常量,这是一个顶层const
const int ci = 42; // 变量自身是常量,这是一个顶层const
const int *p2 = &ci; // 指针所指向的对象是常量,这是一个底层const
const int* const p3 = p2; // 指针本身是常量,靠右的const是顶层const,指针指向的对象是常量,靠左的const是底层const
const int &r = ci; // 对常量的引用都是底层const
注意:底层const的限制不容忽视。当执行对象拷贝操作时,等式左右两边的对象必须具有相同的底层const,或者两个对象的数据类型必须能够转化。一般的,非常量可以转化为常量,反过来则不成立。
int *p = p3; // 错误:p3具有底层const定义,而p没有
p2 = p3; // 正确:p2与p3都是底层const
p2 = &1; // 正确:int* 转化为const int*
// 编译器只会让对引用对象的操作变得更加严格而不是宽松
int &r = ci; // 错误:普通的int&不能绑定到int常量上(对常量操作变宽松,不可以)
const int& r2 = i; // 正确:const int&可以绑定到一个普通int上(对非常量操作变严格,可以)
2.修饰函数
待补充
总结
未完待续