const (constant )不变的,它是定义只读变量的关键字,或者说 const 是定义常变量的关键字。在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。
1.const修饰普通类型的变量
编译器会保持const 修饰的普通类型的变量不变,即使通过其他方式改变了该变量内存中的数据,其变量值仍然保持不变(被编译器优化了)。
#include
using namespace std;
int main(void){
const int a = 7;//volatile const int a = 7;解除const约束
int *p = (int*)&a;
*p = 8;
cout<<a<<" "<<*p<<endl;
// system("pause");
return 0;
}
//输出:7 8
2.const 修饰指针变量
(1)指针常量
先看const再看 * ,p是一个常量类型的指针,不能修改这个指针的指向,但是这个指针所指向的地址上
存储的值可以修改。
(2)常量指针
先看*再看const,定义一个指针指向一个常量,不能通过指针来修改这个指针指向的值。
(3)指向常量的常量指针
对于“指向常量的常量指针”,就必须同时满足上述1和2中的内容,既不可以修改指针的值,也不可以修
改指针指向的值。
//指针常量
int * const p;
//常量指针
const int *p;
int const *p;
//指向常量的常量指针
const int *const p;
可以顺序读,逆序理解(仅为了好记哈)。如指针常量(*前,const后,理解为p是一个常量类型的指针,不能修改这个指针的指向);如常量指针(const前,后,理解为p是一个指针p指向的一个常量,不能通过指针来修改这个指针指向的值)。
3.const参数传递
最常用的有:
a.当 const 参数为指针时,可以防止指针被意外篡改。
b.自定义类型的参数传递,采取 const 外加引用传递的方法,因为临时对象需要复制参数,对于临时对象的构造,需要调用构造函数,比较浪费时间。(并且对于一般的 int、double 等内置类型,我们不采用引用的传递方式。)
4.const修饰类成员函数
const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为 const 成员函数。(使用 mutable 关键字修饰成员函数可修改对象中的该成员)
#include
using namespace std;
class Test{
public:
Test(int _m,int _t):_cm(_m),_ct(_t){}
void Kf()const{
// ++_cm; // 错误
++_ct; // 正确
}
void print(){
cout<<_cm<<" "<<_ct<<endl;
}
private:
int _cm=7;
mutable int _ct=8;
};
int main(void){
Test t(8,7);
t.print();
t.Kf();
t.print();
return 0;
}
注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。
顶层const和底层const
顶层const:指的是const修饰的变量本身是一个常量,无法修改,指的是指针,就是 * 号的右边
底层const:指的是const修饰的变量所指向的对象是一个常量,指的是所指变量,就是 * 号的左边
int a = 10;int* const b1 = &a; //顶层const,b1本身是一个常量
const int* b2 = &a; //底层const,b2本身可变,所指的对象是常量
const int b3 = 20; //顶层const,b3是常量不可变
const int* const b4 = &a; //前一个const为底层,后一个为顶层,b4不可变
const int& b5 = a; //用于声明引用变量,都是底层const
https://interviewguide.cn/notes/03-hunting_job/02-interview/01-01-02-basic.html#_25%E3%80%81c-%E7%9A%84%E9%A1%B6%E5%B1%82const%E5%92%8C%E5%BA%95%E5%B1%82const
《嵌入式软件开发笔试面试指南》
https://www.runoob.com/w3cnote/cpp-const-keyword.html