C/C++ const关键字
const关键字的用法
1)阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
4)对于类的成员函数,若指定其为const类型,则表明其是一个常量函数,不能修改类的成员变量,类的常量对象只能访问类的常量成员函数;
5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。(即返回值无法被赋值)
6)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;
7)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;
8)一个没有明确声明为const的成员函数被看作是将要修改对象中数据成员的函数,而且编译器不允许它为一个const对象所调用。因此const对象只能调用const成员函数。
9)const类型变量可以通过类型转换符const_cast将const类型转换为非const类型;
10)const类型变量必须定义的时候进行初始化,因此也导致如果类的成员变量有const类型的变量,那么该变量必须在类的初始化列表中进行初始化;
11)对于函数值传递的情况,因为参数传递是通过复制实参创建一个临时变量传递进函数的,函数内只能改变临时变量,但无法改变实参。则这个时候无论加不加const对实参不会产生任何影响。但是在引用或指针传递函数调用中,因为传进去的是一个引用或指针,这样函数内部可以改变引用或指针所指向的变量,这时const才是实实在在地保护了实参所指向的变量。因为在编译阶段编译器对调用函数的选择是根据实参进行的,所以,只有引用传递和指针传递可以用是否加const来重载。一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来。函数重载机制会自动假装忽略掉顶层const而保留底层const。当然,当我们传递一个非常量对象或者指向非常量对象的指针时,编译器会优先选用非常量版本的函数。
顶层const(top-levelconst)与底层const(low-levelconst)。
用顶层const(top-levelconst)表示指针本身是一个常量,而用底层const(low-levelconst)表示指针所指的对象是一个常量。由指针引入,更一般的,顶层const可以表示任意的对象(任何数据类型)是常量。而底层const则与指针和引用等复合类型的基本类型部分有关。
对于拷贝操作,顶层const没有什么要求,而底层const要求左值必须比右值更严格。
拷贝操作时,对于顶层const,可以把一个顶层const值赋给一个非顶层const变量,也可以把一个非顶层const值初始化给一个顶层const值。
拷贝操作时,对于底层const,左值必须和右值相同或更严格。也就是说,对于指针和引用,如果右值是const,则左值必须是底层const。
const成员函数的理解和应用?
①const Stock& Stock::topval(②const Stock& s)③const
①处const:确保返回的Stock对象在以后的使用中不能被修改
②处const:确保此方法不修改传递的参数S
③处const:保证此方法不修改调用它的对象,const对象只能调用const成员函数,不能调用非const函数
指针和const的用法
1)当const修饰指针时,由于const的位置不同,它的修饰对象会有所不同。
2)int* const p2 中const修饰p2的值,所以理解为p2的值不可以改变,即p2只能指向固定的一个变量地址,但可以通过*p2读写这个变量的值。顶层指针表示指针本身是一个常量。(指针常量)
3)int const* p1或者const int* p1两种情况中const修饰*p1,所以理解为*p1的值不可以改变,即不可以给*p1赋值改变p1指向变量的值,但可以通过给p1赋值不同的地址改变这个指针指向。底层指针表示指针所指向的变量是一个常量。(常量指针)
4)int const* const p。(指向常量的指针常量)
注意:无论是指针常量还是常量指针,其最大的用途就是作为函数的形式参数,保证实参在被调用函数中的不可改变特性。
一个参数可以既是const又是volatile吗?
可以,用const和volatile同时修饰变量,表示这个变量在程序内部是只读的,不能改变的,只在程序外部条件变化下改变,并且编译器不会优化这个变量。每次使用这个变量时,都要小心地去内存读取这个变量的值,而不是去寄存器读取它的备份。
注意:在此一定要注意const的意思,const只是不允许程序中的代码改变某一变量,其在编译期发挥作用,它并没有实际地禁止某段内存的读写特性。
const与#define的区别:
1)const定义的常量是变量带类型,而#define定义的只是个常数不带类型;
2)define只在预处理阶段起作用,简单的文本替换,而const在编译、链接过程中起作用;
3)define只是简单的字符串替换没有类型检查。而const是有数据类型的,是要进行判断的,可以避免一些低级错误;
4)define预处理后,占用代码段空间,const占用数据段空间;
5)const 不能重定义,而 define 可以通过#undef 取消某个符号的定义,进行重定义;
6)define独特功能,比如可以用来防止文件重复引用。