文章目录
- const 关键字的理解
- 一、 修饰普通类型的变量
- 二、const 修饰指针变量
- 三、const 作参数传递 和 函数返回值
- (1)const 修饰函数参数
- (2)const 修饰函数返回值
- 四、const修饰类成员函数
- 结尾
const 关键字的理解
const
在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数。
C++中, const允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。
使用const有以下好处:
-
编译器的静态检查:const 可以让编译器在编译时进行静态检查,确保不会对被声明为 const 的值进行修改。如果尝试修改 const 值,编译器将产生错误或警告。
-
代码可读性和维护性:使用 const 可以清晰地表达代码的语义,指出某个值不会被修改。可以提高代码的可读性,并且在维护代码时能够更好地理解和推理代码的含义。
-
防止意外修改:通过使用 const,可以避免在代码中意外地修改某个值。特别是当多人协作开发或者代码规模较大时,const 可以起到约束和保护的作用,防止错误的修改。
-
优化机会:const 还给编译器提供了一些优化机会,因为编译器知道 const 值不会被修改,可以进行一些相关的优化操作,提高程序的执行效率。
👇下面我们看const 关键字的使用👇
一、 修饰普通类型的变量
观察下面的代码:
const int a = 10;
int b = a; // 正常赋值
a = 20; // 错误,不能给常量赋值
当使用const
修饰普通类型的变量a时,该变量a会被编译器看成常量,而对常量赋值是违法的。
当我们写出如下的代码时,会发生一些出乎意料的情况:
我们发现,尽管在监视中a的值为20,但最终输出结果依然为10。
这是因为 编译器对常量的优化处理,将常量 a 存储在只读内存区域,并且优化后的指令可能直接使用常量的值。虽然通过指针修改了数据,但是由于常量 a 是不可修改的,所以它的值仍然保持着 10。
上面的例子告诉我们,在c++中,尽量不要修改const修饰的变量。
但我们可以使用volatile
关键字,即下面的写法:
volatile const int a = 10;
当执行上面的代码时,最后结果会输出 “a的值为:20”
这是因为 volatile 关键字告诉编译器,这个变量的值可能会被意外地修改,因此每次使用这个变量时都要从内存中读取,而不是使用已经存在的寄存器中的值。如果没有使用
volatile,编译器可能会对这个变量进行一些优化,例如缓存这个变量的值,这样就无法保证每次使用这个变量时都是最新的值。
二、const 修饰指针变量
const
修饰指针变量有三种情况:
① const 修饰指针指向的内容,则内容为不可变量。
② const 修饰指针,指针为不可变量。
③ const 同时修饰指针和指针指向的内容,指针和指针指向的内容都为不可变量。
对于 ①:
即 const修饰的常量指针:指针本身是一个常量,不能修改指向的地址,但可以修改指向地址所存储的值。
// 理解为: const在int*前,所以
int a = 10, b = 20;
const int* ptr = &a;
// 修改指向地址所存储的值是合法的
*ptr = 20; // 错误,编译器会报错
// 修改指向的地址是不合法的
ptr = &b; // 合法,可以修改指针指向的地址
对于②:
即 const修饰的指针常量:指针指向的是一个常量,不能通过指针修改所指向地址处的值,但可以修改指针指向的地址。
int a = 10, b = 20;
int* const ptr = &a;
// 修改指向地址所存储的值是合法的
*ptr = 20; // 合法,可以修改指向地址处的值
// 修改指针指向的地址是不合法的
ptr = &b; // 错误,编译器会报错
对于③:
即 const同时修饰指针和常量:既不能修改指针本身,也不能通过指针修改所指向地址处的值。
int a = 10, b = 20;
const int* const ptr = &a;
// 修改指向地址所存储的值是不合法的
*ptr = 20; // 错误,编译器会报错
// 修改指针指向的地址是不合法的
ptr = &b; // 错误,编译器会报错
三、const 作参数传递 和 函数返回值
(1)const 修饰函数参数
const 修饰 函数参数有以下三种情况:
- const修饰的值传递参数
void func(const int num) {
// 不能修改num的值
// ...
}
在这种情况下,形参 num 被声明为常量,函数内部不允许修改它的值。
- const修饰的指针传递参数
void func(const int* ptr) {
// 不能修改ptr所指向地址处的值
// ...
}
这里 ptr 是一个指向常量整数的指针,函数内部不能通过指针修改所指向地址处的值,但可以修改指针本身。
- const修饰的引用传递参数
void func(const int& ref) {
// 不能修改ref所引用的值
// ...
}
在这种情况下,引用 ref 被声明为常量,函数内部不允许修改它所引用的值。
(2)const 修饰函数返回值
const 修饰返回值一样有下面三种情况:
- const 修饰返回值为常量:
const int func() {
// ...
return 10;
}
在这种情况下,函数 func() 的返回值被声明为常量,外部代码不能修改返回值。
- const 修饰返回指针类型的函数
int* const func() {
// ...
static int num = 10;
return #
}
这里 int* const 表示返回值是一个指向整数的常量指针。使用 const 修饰的指针表示指针本身的值是常量,外部代码不能修改指针指向的地址。但可以通过指针修改所指向地址处的值。
- const 修饰返回引用类型的函数
const int& func() {
// ...
static int num = 10;
return num;
}
在这种情况下,返回值是一个指向整数的常量引用。使用 const 修饰的引用表示外部代码不能通过引用修改其所引用的对象。
四、const修饰类成员函数
const 修饰类成员函数,其目的是防止成员函数修改被调用对象的值,如果我们不想修改一个调用对象的值,所有的成员函数都应当声明为 const 成员函数。
注意:const 关键字不能与 static 关键字同时使用,因为 static 关键字修饰静态成员函数,静态成员函数不含有 this 指针,即不能实例化,const 成员函数必须具体到某一实例。
有下面两种类型:
- const 修饰返回引用类型的函数
class MyClass {
public:
void func() const {
// ...
}
};
在这种情况下,成员函数 fnc()
被声明为 const
成员函数。const 成员函数表示该函数不会修改类的成员变量。
在 const 成员函数中,不能修改非静态成员变量(除非是 mutable 修饰的成员变量),也不能调用非 const 的成员函数。
- const 修饰返回值为常量的成员函数
class MyClass {
public:
int getValue() const {
// ...
return value;
}
private:
int value;
};
在这种情况下,成员函数 getValue()
被声明为 const
成员函数,并且返回值的类型是 const。这表明该成员函数不会修改类的成员变量,并且返回值在外部代码中不能被修改。
结尾
使用 const 修饰类成员函数可以提供额外的安全性和约束,通过 const 修饰的成员函数,编译器可以对其进行一些优化,在某些情况下还能够调用 const 成员函数来访问 const 对象。同时,也能够帮助开发人员识别和避免意外的修改操作。