C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,可以减少奇怪的BUG。
对于指针和引用类型,const一般分为顶层const和底层const。顶层const就是表示自己本身是常量,不能改变。底层const就是表示自己所引用的或指向的是常量,不能改变自己指向或引用的对象的值。
从上面就可以知道,对于一般类型(非指针或引用), 如int, const指的就是顶层引用了,表示自己是常量,因为他们不能指向或引用别人。
对于一般的const用法在此就不再阐述,这里以const 修饰指针为例,修饰引用与此大致相同。
#include<iostream> using namespace std; int main(){ int a1=3; ///non-const data const int a2=a1; ///const data int * a3 = &a1; ///non-const data,non-const pointer const int * a4 = &a1; ///const data,non-const pointer int * const a5 = &a1; ///non-const data,const pointer a5 = &a2; //error *a4 = 13; //error int const * const a6 = &a1; ///const data,const pointer const int * const a7 = &a1; ///const data,const pointer int * const a8 = &a2; //error,a8 points to non-const data and a2 is const const int * a9 = &a2; //*a9 = 10; return 0; }示例的代码如上。总结,const修饰指针时,
位于 * 左边的是底层const,如 const int *,也就是表示指针所指数据是常量,不能通过解引用修改该数据;但是指针本身是变量,可以指向其他的内存单元。位于 * 右边的是顶层const,如 int * const,也就是表示指针本身是常量,不能修改指针本身的指向。当左右都有 const 时, 聪明的读者可能已经知道了,这时上述两个特点都具备,也就是指针本身是常量,指针指向的也是常量。可能有人会记住这么复杂的规则,在这里介绍个小技巧,可以轻松记住。首先以 * 为分隔符,* 号 右边的 const 因为离 指针名近,所以它表示的是指针本身的const状态,为顶层const。 * 左边的const 离变量名远,所以他表示的是指向的对象的const状态,为底层const。
同时,从上述代码 a8 可以看出,a8所指向的a2是const 类型,所以 a8 的类型应该有一个底层const,代表它指向的是常量数据,底层const位于 * 左边,所以 a8 的类型可以是 const int * 或者 const int * const。在示例代码中a8的类型是int * const, 没有底层const,所以会报错。
传递过来的参数在函数内不可以改变,与上面修饰变量时的性质一样。
void testModifyConst(const int _x) { _x=5; ///error }
注意:const 修饰函数只能用来修饰成员函数,不能是不在类里面的普通函数,同样也不能是类的静态函数,下面会讲这样的原因。非静态的成员函数中都会有一个默认的 this 指针,指向一个实例,this指针默认是 <classname> * const this, 即 改变this的指向,加上 const 关键字之后 会给 this 指针 加一个底层const,即 this指针的类型变为 const <classname> * const this, 意味着不能通过 this 指针 去修改实例的属性。这里隐藏的一个知识点是实例的访问其实都是通过this指针访问的,如上所示 a = 1 这条语句 其实 是 this-> a = 1; 只是编译器替我们做好了这一部分工作。
此外,在写成员函数时一定要考虑是否要加const,不加const 意味着这个成员函数将无法应用于const 类型的实例,因为此时的this 指针类型是 <classname> * const this,而入的实例类型是 const <classname> a, 转换后的this指针类型是const <classname> * const this, 两者无法直接转换。所以要考虑这个成员函数是否需要作用在 const实例上 以及函数内部是否需要修改属性。
4. const 修饰函数返回值
待补充
参考资料:C++ const用法 尽可能使用const
