有趣的const
c语言初步了解const
之前学习c语言时没有过多了解,现在做个小小的总结。
const是一个C语言(ANSI C)的关键字,具有着举足轻重的地位。它限定一个变量不允许被改变,产生静态作用。使用const在一定程度上可以提高程序的安全性和可靠性。
下面介绍一下它的具体功能:
1.修饰变量
const int a=2;
上面这个例子表明,变量i具有只读特性,不能够被更改;若想对a重新赋值,如a= 5;则是错误的。
定义变量的同时,必须要初始化。定义形式也可以写成int const a=2
此外,const修饰变量还起到了节约空间的目的,通常编译器并不给普通const只读变量分配空间,而是将它们保存到符号表中,无需读写内存操作,程序执行效率也会提高。
2,修饰指针
int i=7;
int j=5;
int a=0;
const int *p=&i;//定义的第一种
int *const q=&j;//定义的第二种
在第一种定义下p的指针所指向的地址空间的值将不会改变,若是执行 *p=8 就会报错,但是可以改变p指针的地址,例 p=&a 是可以运行的。
而在第二种定义下q的指针const是针对q定义的,所以和第一种的效果相反,若是执行 *q=8 是可以正常运行的,而 q=&a 会报错。
3.修饰数组
C语言中const还可以修饰数组,举例如下:
const int a[6] = {0,1,2,3,4,5};
a[0] = a[0]+1; //错误
数组元素与变量类似,具有只读属性,不能被更改;一旦更改,如程序将会报错。
4.函数参数修饰
void func1(const int i){
i++;//对i的值进行修改,程序报错
}
void func2(const int *j){
(*j)++;//对j的值进行修改,程序报错
}
cpp再次加深理解
1.const一般用法:
先来看一个简单的例子
const int num = 512; //先声明一个整形常量
num = 10;
这样便出错,和c语言一样因为试图向一个const对象写值
再区别一下指针类型的const声明
int i = 10;
int b = 20;
/*(1)*/ const int *p = i;
/*(2)*/ int *const p = &i;
/*(3)*/ const int *const p = &i;
这种声明我们一般从右向左来看
- /* (1) */:这条声明const是将 *p 也就是将 p 指向的值作为常量,若要更改
*p = 9
则会报错 - /* (2) */:这条声明const是将 p 指针作为常量指针,如果要更改
p = &b
则会报错 - /* (3) */:这条声明const是既将 p 指针作为常量指针,又将该指针所指向的值作为常量
注:使用const是要将对象初始化,如果不初始化const也没有任何意义,只会报错
2.文件中的用法:
如果一个程序包含多个文件,那么有一个问题,如何让用了const变量都访问到初始值,在这里我们引入extern
关键字,只需在每个const前填上该关键字则可以让其在文件中共享
extern const int bufsize = size(); //在file_1.cc中
extern const int bufsize; //在file_1.h中,与file_1.cc中是同一个
3.const的引用:
可以将一个引用绑定到const对象上,但是只要绑定到const的对象上就不能修改该对象(const限定了呗)
举个例子:
const int i = 100; //正确,初始化一个const对象为常量
const int &r = i; //正确,引用常量 i 绑定到常量 r上
int &r2 = i; //错误,不可以用非常量 r2 来引用常量 i;
r = 20; //错误,r是对常量的引用,不能再对其赋值
但是对于const的引用可能引用一个非const的对象,如下例:
int i = 20; //初始化
int &r1 = i; //正确,非常量 r1 引用非常量 i;
const int &r2 = i; //正确,常量 r2 引用非常量 i;
r1 = 0; //正确,此时i = 0, r1 = 0;
r2 = 0; //错误,因为 r2 是常量,不可修改其值,但由于 r1 引用 i 将值变为0,则r2此刻也为0
4.顶层const
由于牵扯到指针后会区分指针这个对象本身以及它所指向的对象两个对象,所以就有了顶层和底层两个概念,顶层也就是说指针本身为常量则为 顶层const 而指针所指向的对为常量的话则成为底层const,但是注意一点,以上为复合类型,当我们单独声明一个const常量一般都称为顶层const,而单独的指针声明既可以是顶层const也可以是底层const引入这两个概念我们再看一些例子
int i = 0;
int *const a = &i; //正确初始化,不能修改层const对象(a)
const int m = 42; //正确初始化,不能修改顶层const对象(m)
const int *p1 = &m; //正确,都具有底层const对象类型
const int *const p = 10; //从右向左看第一个为顶层const,第二个则为底层const
const int &r = i; //一般用于声明引用的都为底层const
/*******************************************/
//当对上面的定义的对象执行拷贝操作时,区别明显,一般顶层const不受影响
i = m; //正确,顶层const不受影响
p1 = p; //正确,都具有底层const的对象类型,p的顶层const不受影响
int *p2 = p; //错误,p有底层const限制,但是p2没有
p1 = &i; //正确,int *将转化为const int *
int &c = m; //错误,因为普通的int &不能绑到一个int常量上
const int &r2 = i; //正确,int 常量可以绑定 int 非常量上