「C++笔记」const限定符
const限定符
const
- const限定符用于定义常量:
- 常量:一旦创建后其值就不可改变
- const对象必须初始化
1
const int var = 42; //定义一个名为var的int常量
作用域
- 默认情况下,const对象被设定为仅在文件内生效
- 若需要const对象能被其他文件访问,须在声明或定义时添加
extern关键字1
2
3
4//A.cc
extern const int var = 42; //在A.cc中定义var
//B.cc
extern const int var; //在B.cc中声明var
const与引用
- 对const的引用(C++程序员常通俗称作常量引用):
- 常量引用引用的对象可以是非常量对象,其不可用作修改所引用的对象,引用非常量对象时可通过其他途径修改所指对象的值
- 引用常量对象只能使用常量引用
1
2const int var = 42;
const int &rf = var; - 常量引用初始化时可以绑定任意表达式,只要其结果可以转换为引用类型,这会为此常量引用绑定临时量
1
2
3
4
5
6
7// Your code
double var = 1.61;
const int &rf = var;
// 概念上,编译器会这样解释
double var = 1.61;
const int temp = var; //将var转换为临时int常量
const int &rf = temp; //让rf绑定临时量
常量引用实际并不存在,引用并非一个对象,无法使其本身保持不变,这仅是C++程序员约定俗成的称呼
const与指针
- 指向常量的指针:
- 指向常量的指针可以指向非常量对象,其不可用于修改所指向的对象,指向非常量对象时可通过其他途径修改所指对象的值
- 指向常量对象只能使用指向常量的指针
1
2const int var = 42;
const int *ptr = &var;
- 常量指针
- 指针作为一个对象,可以将其本身定义为一个常量,这会使其存放的地址无法改变,而非指向的值,常量指针必须初始化
1
2int var = 42;
int *const ptr = &var;
- 指针作为一个对象,可以将其本身定义为一个常量,这会使其存放的地址无法改变,而非指向的值,常量指针必须初始化
理解声明符:从右向左读,以
int *const ptr = &var;为例:
将var的地址赋予名为ptr的对象(ptr = &var) –> ptr是常量对象(const ptr) –> 常量对象ptr是一个指针(*const ptr) –> 常量指针ptr指向int对象(int *const ptr) –> ptr是一个指向int对象var的常量指针
const层级
- 顶层const表示对象是常量,底层const与复合类型的基本类型部分有关,表示绑定的对象是常量:
1
2
3
4
5
6
7
8
9
10int var = 0;
int *const ptr = &var; //顶层const,ptr的值不可修改
const int cvar = 42; //顶层const,var的值不可修改
const int *ptr1 = &var; //底层const,ptr的值可以修改
const int &r = cvar; //底层const,r引用的对象可变更
const int *const ptr2 = ptr1;
/* 靠右的const是顶层const,它使ptr2的值不可改变,另一个是底层const
*/ - const层级与拷贝赋值:
- 拷贝操作不会修改对象的值,因此顶层const无明显影响:
1
2var = cvar; //Valid
ptr1 = ptr2; //Valid- 但底层const限制必须拷入和拷出的对象具有相同层级的const,或者可以转换:
1
2
3
4
5
6
7
8
9
10
11
12
13int *p = ptr2; //Invalid,ptr3有底层const,p没有
ptr1 = ptr2; //Valid,都有底层const
ptr1 = &var; //Valid,var的地址int*可以转换为const int*
int &r = cvar; //Invalid,cvar有底层const,r没有
const int &r2 = var //Valid,const int&可以绑定int,满足转换条件
* * *
## 常量表达式
- **常量表达式**是指值不会改变且在**编译时**就可以得到值的表达式,由它的数据类型和初始值决定
```C++
const int A = 42; //A为常量表达式
const int B = A + 1; //B为常量表达式
int C = 9; //C不是常量,不是常量表达式
const int size = get_size(); // 除非get_size()是constexpr函数,否则这不是常量表达式 - constexpr类型
- 将变量声明为constexpr类型以告诉编译器验证变量是否为常量表达式,声明的变量一定是常量,且必须使用常量表达式初始化;普通函数不可以作为constexpr变量的初始值,必须为constexpr函数(在编译时就能获得其值)
- constexpr隐含顶层const
- constexpr定义时用到的类型必须为字面值类型——简单、值显而易见的类型(算数类型、指针、引用等)
1
2
3constexpr int A = 20; //Valid
constexpr int B = A + 1; //Valid
constexpr int size = getSize(); //只有getSize是constexpr函数式此语句才正确当你笃定一个变量是常量表达式时,就应该把它声明为constexpr类型
- constexpr与指针:
- 在constexpr声明中定义一个指针,constexpr只对指针生效,与其所指向的对象无关;它也可以指向非常量
- constexpr指针初始化时必须绑定具有固定地址的对象或为空指针
易错
- 指向常量的指针和对const的引用“自以为”它们绑定了一个常量(即使是非常量),因此无法通过它们改变所绑定对象的值,但可以通过其他方式改变
- 指向常量的指针VS常量指针
指向常量的指针 常量指针 特性 不可以 可以 是否可以通过它修改所指向的非常量的值 可以 不可以 是否可以修改其所指向的地址 可以 不可以 是否可以指向常量 底层const 顶层const const层级 - 两者结合既不可以通过它修改所指向的非常量的值,又不可以修改其所指向的地址,但可以指向常量(右到左读法理解=>指向常量的常量指针)
- constexpr声明中定义的指针为常量指针
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 ✨岚的小窝✨!
评论



