const关键字不同使用场景
const关键字它主要用于声明常量,这意味着一旦一个变量被声明为常量,其值就“不能被改变”,这个“不能被改变”也不是绝对的不能发生任何变化,具体场景如下:
1.声明常量变量:
常量变量在编译时赋值,并且在其生命周期内不能发生改变。
int main() {
const int const_val = 1;
const_val = 2; // 错误,不能对常量const_val修改
return 0;
}
2.指针和常量:
1.指向常量的指针:
这样的指针不能修改它所指向的值,但可以更改指针本身所指向的地址。
int val = 1;
const int* p = &val; // 这种情况下,可以理解为,const修饰的是“值”
// *p = 2; // 错误,不能修改p所指向的值
int new_val = 2;
p = &new_val; // 正确,可以更改p的指向
2.常量指针:
这样的指针的值(即它所指向的地址)在初始化后不能更改,但可以通过该指针修改它所指向的值(除非该值本身也是常量)。
int val = 1;
int* const p = &val; // 这种情况下,const修饰的是指针,所以指针指向的地址不能改变
*p = 2; // 正确,可以修改所指向的值
int val2 = 2;
p = &val2; // 错误,不能更改指针p的地址指向
3.指向常量的常量指针:
这种指针既不能修改它所指向的值,也不能更改它所指向的地址。
int val = 1;
const int* const p = &val; // const既修饰了指针地址,又修饰了“值”
*p = 2; // 错误,不能改变p的值
int val2 = 2;
p = &val2; // 错误,不能改变p所指向的地址
3.函数参数中的 const
在函数参数中使用 const 可以防止函数内部修改传入参数的值。
void test(const int val) {
//val = 2; // 错误,不能对val的值进行修改
cout << val;
}
4.函数返回值的 const
如果一个函数的返回值是 const,那么它不能被修改。
const int test() {
int val = 2;
return val;
}
int main() {
cout << test()++ << endl; // 错误,不能对test函数的返回值进行修改。
return 0;
}
5.类成员函数的 const
在类的成员函数声明后面加上 const 关键字(称该函数为常函数),表示该函数不会修改类的任何成员变量(除非这些变量被声明为 mutable)。
class MyClass {
public:
int getValue() const {
value_++; // 错误,不能修改成员变量
value2_++; // 正确,被mutable修饰,可以修改
return value_; // 可以读取value_,但不能修改它
}
private:
int value_;
mutable int value2_;
};
6.数组中的 const
const 可以用于数组的声明,表示数组的内容不能被修改。
const int arr[] = { 1, 2, 3, 4, 5 };
arr[0] = 6; // 错误:不能修改const数组的内容
7.在函数体内声明 const:
在函数体内,可以使用 const 来定义临时常量,有助于增加代码的可读性和安全性。
void test() {
const int tmp = 1;
tmp = 2; // 错误,tmp不能被修改
}
扩展
const和define的区别和优缺点。
const:
- const是C++中的关键字,用于定义常量。
- const定义的常量具有类型,可以进行类型检查。
- const常量在编译时分配内存,并且有作用域限制,只在定义的作用域内有效。
- const常量可以通过地址获取,可以取得其指针。
- const常量可以用于函数参数和返回值类型,以及类的成员变量和成员函数。
优点:类型安全、可读性好、可以进行编译器优化。
缺点:不能用于定义复杂的常量表达式,只能定义简单的常量。
define:
- define是C/C++中的预处理指令,用于定义宏常量。
- define定义的常量没有类型,不进行类型检查。
- define常量在预处理阶段进行简单的文本替换,没有内存分配和作用域限制。
- define常量不能获取其地址,也不能取得其指针。
- define常量只是简单的文本替换,不会进行任何计算。
优点:可以定义复杂的常量表达式,可以用于任何地方。
缺点:没有类型安全性、可读性差、可能会导致预期外的替换错误。