一、const的定义
- const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。
二、const的由来
- 最初的目的是为了取代预编译指令define,继承define的优点并且摈弃它的缺点。
举两个例子:
1.从内存角度
#define MAX_D 10
const int MAX_C = 10; //此时保存在符号表,未分配内存
int main(void)
{
int num_d = MAX_D; //预编译过后这句话就是int num_d = 10;(分配内存)
int num_c = MAX_C; //第一次MAX_C分配内存
int num_d1 = MAX_D; //预编译替换(分配内存)
int num_c1 = MAX_C; //之后MAX_C就不分配内存
return 0;
}
2.从语句使用:(const能避免一些宏define因为括号引起的错误)
#define MAX_D 10 + 20
const int MAX_C = 10 + 20;
.....
int num_d = MAX_D / 2; //因为宏的特性预编译后num_d = 10 + 20 / 2
int num_c = MAX_C / 2; //执行后num_c = 30 / 2;
3.小结
- 数据类型:cosnt修饰的变量有明确的类型,而宏没有明确的数据类型(不安全,但很灵活->很强大)
- 安全方面:const修饰的变量会被编译器检查,而宏没有安全检查,可能会发生意外的错误(边界效应)
- 内存分配:cosnt修饰的变量只会在第一次赋值时分配内存,节省空间,避免不必要的内存分配,同时- - 提高效率,而宏是直接替换,每次替换后的变量都会分配内存
- 作用场所:const修饰的变量作用是在编译、运行过程中,而宏作用在预编译
- 代码调试:cosnt方便调试,宏在预编译进行所以没法调试。
三、const的使用
-
1.修饰只读常量,不能被改变。改变报错。
-
2.修饰一般变量(const的位置可以在类型说明符前或后)
int const num=2;
const int num=2;
- 3.修饰只读数组(const的位置可以在类型说明符前或后)
int const num[2]={1, 2};
const int num[2]={1, 2};
- 4.修饰引用
- 语法:const int &a = s;//这里不能对a进行修改而改变s的值,但是可以改变s。
int const &s = a;//这里const int &s =a效果等效。
- 5.修饰指针(四种形式)
const int *ptr; //ptr可变,指向对象不能变
int const *ptr; //ptr可变,指向对象不能变
int * const ptr; //ptr不可变,指向对象可变
const int * const ptr; //ptr都不可变
我也搞混淆了很多次,不过总结了一下,在分析就完全ok了。
①首先我们得知道const一次只能修饰一个变量
②然后我们得根据就近原则,所谓“近水楼台先得月”来判断哪个变量跟cosnt最近,是(*ptr)还是ptr。
③之前也有提到const的位置可以在类型说明符前或后。
const int *ptr; //const与*ptr近,与ptr远
int const *ptr; //const与*ptr近,与ptr远
int * const ptr; //const与ptr近,已经拆分了*ptr
const int * const ptr; //第二个const与ptr近,第一个const显然与(* const ptr)近
- 6.修饰函数参数
void Fun(const int *p); //意义指针变量本身可变,p所指向的变量不可变
void name () const;
/*
函数声明尾加const说明这个函数不可以修改类的成员变量(或者说不可以改变对象的内部状态)。因此,加了const的函数:
(1)不能修改成员变量;
(2)不能调用非const函数;
(3)其他const函数可以调用它;(其他非const函数当然也可以调用它)
(4)只能从const对象(或引用用指针)上调用,比如:const A a; a.f();
*/
①告诉编译器传入参数不能改变,防止使用者的无意或错误的修改
②修饰指针传参,就是在声明函数内部不会改变这个指针所指向的内容。(一般是做函数输入参数)
③补充:这也可以只知道函数原型时可以大概去判断函数列表里的输入参数与输出参数
- 7.修饰返回值
const int Fun (void); //返回值不可被改变。
四、补充
- 1.const常量可以被改变(gcc环境下)
const int num = 5;
int *p = (int *)# //强制类型转换来消除警告;
*p = 10;
printf("num = %d.\n", num); //num = 10,const类型的变量被修改
原因:
①const在c的规定中并未有明确规定,const修饰的变量存放在哪里
②在gcc环境下,const是通过编译器在编译的时候执行安全检查,在程序运行过程中并不会报错。
③内存的储存上,gcc把const类型的常量也放在了data段
④所以根据这些特性,通过强大的指针骗过编译器就可以改变了
五、总结
1.const的合理使用能告诉编译器哪些变量不希望改变,防止无意的被修改,减少bug,也使代码更严谨。
2.const的使用也是为读代码的人传递很有用的信息,间接或直接告诉使用者这个变量不应该被修改。