首页 > 代码库 > C++中const限定符的应用

C++中const限定符的应用

const限定符用于限定变量或对象的值。const对象一旦创建其值不能再改变。在C++中,const与引用和指针相结合,有多种用法。下面将结合<C++ Primer>第五版的内容做一个较详细的介绍。

1.const对象初始化

const对象必须初始化,初始化可以是任意复杂的表达式,如:

    const int i=get_size();

    const int j=42;

2.文件间共享const对象

当以编译时初始化的方式定义一个const对象时,编译器将在编译过程中把用到该变量的地方都替换成对应的值。替换的前提是编译器知道变量的初始值。为了避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。值得注意的是,当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。

文件间共享const变量,即希望编译器不会为每个文件分别生成独立的变量。解决的办法是,对于const变量不管是声明还是定义都添加extern关键词,这样只需定义一次就可以,如: 

    //  file_1.cc中定义并初始化了一个常量,该常量能被其他文件访问     

    extern const int bufSize=fcn();

    // file_1.h头文件中对bufSize进行声明

    extern const int bufSize;

3.const的引用

对const的引用通常也被简称为“常量引用”(reference to const)。不同于普通引用,对常量的引用自身也是const类型。如:

     const int ci=1024;

     const int &r1=ci;                     //注意这里的引用是常量,去掉const错误

常量引用仅对引用可参与的操作作出限定,对于引用的对象本身是不是一个常量未做先限定。如:

     int i=42;

     int &r1=i;                               //引用r1绑定对象i

     const int &r2=i;                      //r2也绑定对象i,但是作为常量引用,不允许通过r2修改i的值

4.指针和const

4.1指向常量的指针

与引用类似,想要存放常量对象的地址,只能使用指向常量的指针(pointer to const)。如:

    const double pi=3.14;

    const double *cptr=&pi;

和常量引用一样,指向常量的指针也没有规定其所指的对象必须是一个对象,即对const的引用和指针都必须是const类型的,但const类型的指针和引用也可以针对非常量的对象。如:

    double dval=3.14;                    //dval是一个双精度浮点数,非常量

    cptr=&dval;                             //指向常量的指针cptr也可以指向dval

4.2常量指针

指针本身也是对象,可以把指针本身定义为常量,称为常量指针(const pointer)。常量指针必须初始化,一旦初始化后其值(存放在指针中的地址)不再变化。把*放在const关键词之前用以说明指针是一个常量。如:

     int errNumb=0;

     int *const curErr=&errNumb;    //curErr为常量指针,将一直指向errNumb

     const  double pi=3.14159;

     const double *const pip=&pi;    //pip是一个指向常量对象的常量指针

对于较复杂的定义,可采取从右向左阅读的有效方法。如pip,离pip最近的是const说明pip为常量,加上*说明pip为常量指针,double说明pip指向double类型对象,const说明pip指向的是常量。

4.3顶层const和底层const

狭义的讲,顶层const(top-level const)表示指针本身是个常量,相对的底层const(low-level const)表示指针所指的对象是一个常量。

广义来讲,顶层const可以表示任意的对象是常量,且对任何数据类型都适用。底层const则与指针和引用等复合类型的基本类型部分有关。比较特殊的是,指针类型既可以是顶层const,也可以是底层const。来看几个例子:

      int i=0;

      int *const p1=&i;                   //p1为常量指针,本身是一个常量,为顶层const

      const int ci=42;                     //ci为常量,是顶层const

      const *p2=&ci;                       //p2为指向常量的指针,其本身的值可以变,为底层const

      const int *const p3=p2;         //靠右的为顶层const,靠左的是底层const,p3既是顶层const也是底层const

      const int &r=ci;                      //引用本身不是对象,用于申明引用的const都是底层const

在执行拷贝操作时,常量是底层const还是顶层const区别明显,我想这也是将二者进行明显区分的意义所在。顶层const不受拷贝影响:

      i =ci;                                     //拷贝ci的值,ci是一个顶层const,对此操作无影响

      p2=p3;                                 //p2和p3指向的对象类型相同,p3顶层const的部分不影响

另一方面,底层const受拷贝限制明显。当执行对象的拷贝操作时,考拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转化为常量。

      p2=p3;                                //两者都具有底层const的属性

      p2=&i;                                 //i为普通int变量,int*能转换为const int*

      const int &r2=i;                    //引用为底层const,可以绑定到普通int上

5.总结

const作为单纯的常量本身并不复杂,但是与引用和指针相结合以后则较为复杂,需要厘清其中的关系,才能做到灵活应用。

参考文献

Stanley B.Lippman,Josee Lajoie,Barbara E.Moo.C++ Primer(5th edition)