在C++编程中,const关键字是一个强大的工具,不仅可以用于定义常量,还能够在函数、类中发挥关键作用。本篇博客将带您深入探索const关键字的魅力,教您如何利用它来提升代码的安全性和可维护性。
文章目录
1. const 修饰普通变量
const关键字不仅可以用于声明常量,还能够保护数据,防止意外的修改。对于不同变量来说,用const修饰普通变量实际上就是定义了一个常量,以下两种定义形式在本质上是一样的。它的含义是:const修饰的类型为TYPE的变量value是不可变的。
const int MAX_VALUE = 100;
另外,在c++中还会用const修饰来代替#define来定义常亮,被修饰变量名通常采用全大写。
实际上,虽然不能直接对常变量进行修改,但是我们可以通过指针对常变量进行修改,也就是通过访问地址去修改
const int n=10;
int *p=&n;
*p=20;
std::cout<<*p<<std::stdl;//屏幕输出值不在是10,而是20
2. const 修饰指针
2.1 const
修饰指针 p
int i = 10;
int* const p = &i;
这表示指针 p
是一个常量指针,即指针本身不可修改。因此,p++
这样的操作是错误的。但是,你仍然可以通过 *p
来修改所指向的变量的值,因为指针所指向的变量并没有被声明为 const
。
*p = 26; // 正确,可以修改所指向的变量的值
2. 2 const
修饰 *p
int i = 10;
const int *p = &i;
这表示指针 p
是一个指向常量的指针,即不能通过指针来修改所指向变量的值。但是,变量 i
本身是可变的,因此你仍然可以通过其他方式来修改 i
的值,例如 i=26
或 i++
。同时,指针 p
本身是可变的,你可以改变它指向的对象,例如 p = &j
。
i = 26; // 正确,可以修改变量i的值
i++; // 正确,可以修改变量i的值
*p = ; // 错误,不能访问地址来修改变量的值
2.3 const
同时修饰指针 p
和 *p
const int* const p;
这表示指针 p
是一个常量指针,同时指向的是一个常量对象。既不能通过指针来修改所指向的变量的值,也不能改变指针 p
指向的地址。
*p = 26; // 错误,不能通过指针修改所指向的变量的值
p++; // 错误,不能修改指针p的指向
关于const
修饰符的位置,const
在*
的前面和后面是等效的,它们都表示指针所指向的变量是常量。
注意以下的区别:
int i;
const int* p1 = &i;//不能通过指针修改
int const* p2 = &i;//不能通过指针修改
int *const p3 = &i;//指针不能修改
3. const 修饰数组
const关键字还可以用于修饰数组,保护数组的每个元素不被修改。这使得代码更加健壮,避免了潜在的错误。
const int SIZE = 5;
const int arr[SIZE] = {1, 2, 3, 4, 5};
通过const修饰数组,我们可以在编译期间就发现并防止对数组的非法修改。
4. const 修饰函数形参
4.1 const
修饰普通形参变量
void function(const int Var);
这种情况下,const
修饰的是函数的形参变量,表示在函数内部不会改变这个变量的值。然而,这在实际中没有太多意义,因为形参本身是函数调用时实参的拷贝,所以实参的值不会改变。
4.2 const
修饰指针形参
void function(const char* Var);
在这种情况下,const
修饰的是指针形参,表示无法通过指针修改其所指向的外部实参,从而保护了数据的安全性。
void function(char* const Var);
然而,如果是这种情况,const
修饰的是指针本身,即指针形参不会改变。但是,我们依然可以通过指针修改传递进来的外部实参,无法保证外部数据的安全性。
4.3 const
修饰引用形参
void function(const int& Var);
在这种情况下,参数为引用,将外部实参传递给引用形参,传递的是外部实参本身,无需进行拷贝,增加了效率。同时,参数是 const
引用,无法通过引用修改实参,保证了外部数据的安全性。
注:
- 如果函数参数是非
const
的引用/指针,它就不能接收const
变量(地址),因为会造成权限的放大,会报错。它只能接收非const
变量(地址)。而如果函数参数是const
的引用/指针,它既可以接收const
变量(地址),也可以接收非const
变量(地址),这是权限的缩小,没有问题。 - 如果函数参数是
const
普通变量,那么它可以接收const
变量,也可以接收非const
变量,因为不会造成权限的放大。
5. const 修饰函数返回值
const修饰普通类型的返回值:
const int fun1();
这个声明表示 fun1
函数返回的是一个 const int
类型的值。在这种情况下,const
关键字对返回值并没有实际影响,因为返回的是一个临时值,无论是否声明为 const
,都不能修改这个临时值。所以,这种用法在实践中确实没有太多意义。
const修饰指针类型的返回值:
const int* fun2();
这个声明表示 fun2
函数返回的是一个指向 const int
类型的指针。这种用法很常见,它表明函数返回的指针指向的是一个不可修改的 int
变量。这样的声明在函数返回指针指向的数据是常量时非常有用,它可以防止通过返回的指针修改数据。
6. const修饰成员变量
当const修饰类的成员变量时,表示该成员变量为常量,不能在类内被修改,同时只能在初始化列表中进行赋值。
class A {
...
const int n; // 成员常量不能被修改
...
A(int x): n(x) { } // 只能在初始化列表中赋值
};
7. const修饰成员函数
将const修饰的成员函数称之为const成员函数。在const成员函数中,this
指针的类型为 const 类型* const this
,即不能修改this
指针本身,但可以修改其所指向对象的非const成员变量。const修饰的类成员函数用于保护对象,确保在该函数中不会对对象的成员变量进行修改。
class Date {
public:
void print() const {
cout << _year << endl;
}
// 该成员函数实际上是这样
/*
void print(const Date *const this) const {
cout << this->_year << endl;
}*/
private:
int _year;
int _month;
int _day;
};
在const成员函数中,this
指针的指向是const的,这意味着不能通过this
指针修改对象的成员变量。