1.问题引入
<span style="font-size:18px;"><span style="font-size:18px;">for( int index =0; index != 512; ++ index){ //...... </span></span>
上面的for循环代码有两个问题,都和512作为循环上界有关。
第一个问题是程序的可读性。比较index和512有什么意义呢???循环在做什么工作呢???也就是说512是什么东西呢???在本例中,512被称为魔数(magic number),它的意义在上下文中没有体现出来,好像这个数是魔术般地从空中出现的。‘
第二个问题是程序的可维护性。假设这个程序非常庞大,512出现了100次。进一步假设在这100次中,有80次是表示某一特殊缓冲区的大小,剩余20次是用于其它的目的。现在我们需要把缓冲区的大小增大到1024。要实现这一改变,必须检查每个512出现的位置。此时我们就要仔细勘察哪一处表示缓冲区,哪一处表示其他目的,要知道,错改一处,都会造成程序的崩溃!!!
解决这两个问题的方法是使用一个初始化为512的对象:
<span style="font-size:18px;">int bufSize = 512; // input buffer size for(int index = 0; index != bufSize; ++index){ //...... }</span>
我们可以看出,现在是对对象bufSize测试,而不是字面值常量512测试。
2.为什么我们需要const?
定义一个变量代表某一常数的方法仍然有一个严重的问题。即 bufSize 是可以被修改的。bufSize 可能被有意或无意地修改。const 限定符提供了一个解决办法,它把一个对象转换成一个常量。
<span style="font-size:18px;">const int bufSize = 512; //input buffer size</span>
定义bufSixe为常量并初始化为512.变量bufSize仍然为一个左值。但是现在这个左值是不可以修改的,修改任何的bufSize的尝试都会导致编译错误。
<span style="font-size:18px;">bufSize = 0; // error: attemp to write to const object</span>
因为常量定义后就不能被修改,所以定义时必须初始化!!!
<span style="font-size:18px;">const std::string hi = "hello";// ok:innitialized const int i,j=0;//error:i is uninitialized const</span>
3.const对象默认为文件的局部变量
在全局作用域里定义非 const 变量时,它在整个程序中都可以访问。我们可以把一个非 const 变更定义在一个文件中,假设已经做了合适的声明,就可在另外的文件中使用这个变量:
<span style="font-size:18px;">// file_1.cc int counter; // defination // file_2.cc extern int counter; // uses counter from file_1 ++counter; //increments counter defined in file_1</span>
与其他变量不同,除非特别说明,在全局作用域声明的 const 变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。
<span style="font-size:18px;">// file_1.cc // defines and initialize a const that is accessible to other files extern const int bufSize = fcn(); // file_2.cc extern const int bufSize; // uses bufSize from file_1 for(int index = 0; index != bufSize; ++ index){ //...... }</span>
在上述程序中,file_1.cc通过函数fcn的返回值来定义和初始化bufSize。而bufSize又被定义为外部类型extern,这就意味着bufSize可以再其他的文件中被使用。file_2.cc中bufSize同样声明为外部类型extern;不能被初始化。
区别:非const变量会被自动默认为extern。而要使const变量能够在其他的文件中访问,必须制动他为extern。