const 修饰符的认识理解与应用
我通过对const 修饰符的学习与同学在一起交流时得知好多人没有把const这个保留字的意义搞清。总是把const与它修饰的空间或指针看做一体,最后关系多了就乱了,不知道到底哪个可以给哪一个,哪个能写哪个不能写。
我自己现在对 const的学习有一个特别的方法,现在拿来与大家讨论一下。我个人的见解一定还有不严谨的之处。望大家批评改正。
好现在开始步入正题!
const的意义: 在可更改与不可更改之间画一条明确的界线,提高程序的安全性和可控性
const int i=100;
i++; //编译错误
这个const修饰的是一个空间说明这个空间里的值是不可改变的。
在C中:
“一个不能被改变的普通变量”。
因此:
-- 总是占用存储;
-- 名字是全局的。也就是说,默认情况下,const是外部连接的(容易引起“名字冲突”)
下面的代码在存为C文件在VC6.0编译器下编译是错误的!为什么?
#include<stdio.h>
void main()
{
const int bufsize = 10 ;
char buf[bufsize] = {'a','b','c'};//error C2057:expected constant expression
//error C2466: cannot allocate an array of constant size 0
printf ("%S",buf);
}
在编译时,编译器并不知道const的值,它只是一个“运行时常量”。不是放在符号表里的。(编译原里的知识这里就不多讲了!)
然而把上面的代码改成CPP文件在VC6.0编译器下编译是通过的。
通常,C++编译器不为const创建存储空间,而是把它保存在“符号表”里,即“编译时常量”。默认情况下,C++中的const是内部连接的,也就是说,const仅在const被定义过的文件里才是可见的。(因此,不用担心名字冲突)当定义一个const时,必须赋一个值给它,除非用extern做出了清楚的说明。当用extern说明了const时,编译器会强制为const分配空间,而不是保存在符号表中。
extern const int bufsize;// 未赋初值,但extern声明了bufsize在另一个文件中定义及赋初值。
const用于集合,必须为其分配内存,(因为编译器“不愿意”把集合保存到符号表中,太复杂)。
#include<stdio.h>
const int bufsize = 10 ;
void main()
{
const int i[] = { 1, 2, 3, 4 };
float f[i[3]]={1,2,3,4,}; //error C2057: expected constant expression
//error C2466: cannot allocate an array of constant size 0
printf ("%S",buf);
}
看起来很像第一个例子在C里面报的错。对,就是同样的错误!
值替代: C++的const vs C中的宏替换
#define BUFSIZE 100; // 宏替换
char str[BUFSIZE];
vs
const int bufsize = 100; // C++的const
char str[bufsize];
在宏替换中,BUFSIZE没有类型信息,不能进行类型检查;
宏定义是全局的,容易名字冲突。
安全性:如果想用运行期间产生的值初始化一个变量,并且知道在该变量的生命期内其值不变,则可用const限定该变量,达到最大限度地保证改变量安全性的目的。
void main()
{
cout << "type a character & CR:";
const char c = cin.get(); //用运行期间产生的值初始化,之后不变
const char c2 = c + 'a';
cout << c2;
}
const char*, char const*, char*const的区别问题几乎是C++面试中每次都会有的题目。
事实上这个概念谁都有只是三种声明方式非常相似很容易记混。
Bjarne在他的The C++ Programming Language里面给出过一个助记的方法:
把一个声明从右向左读。
char * const cp; ( * 读成 pointer to )
cp is a const pointer to char
const char * p;
p is a pointer to const char;
char const * p;
同上因为C++里面没有const*的运算符,所以const只能属于前面的类型。