zoukankan      html  css  js  c++  java
  • 关键字const

    引言

      在C和C++中,限定符const的应用可谓十分常见。我在重现教材书籍code的时候,老是在const的问题上犯迷糊。今天刚忙完导师布置的任务,闲着就像把这个问题说清楚,以后自己再有问题也好自我反省下。

      首先在C语言中,const是一个限定符,它用来限定一个变量不被改变。使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。那么具体来看,const被用在什么地方呢。

      我将从以下4点来讲解const限定符的用法:

              1、对象与const

                2、引用与const

              3、指针与const  

              4、函数与const

    1、对象与const

      这是最直观的用法。比如我们有以下代码:

           const int bufSize = 512;

         定义bufSize为常量且初始化为512。此后,任何尝试修改bufSize的尝试都会导致编译错误,例如 bufSize = 100; 

      此外,还要注意的是:

           const  std::string hi = "hello!";  //正确
           const  int i, j = 0;               //错误,i 没有初始化

        因为作为const常量在定义后就不能修改,所以定义时必须初始化。

    2、引用与const

      先复习一下引用。引用就是它绑定的对象的另一个名字,例如:张三有个小名“阿三”,叫“阿三”就是叫张三这个人,那么“阿三”就是张三的别名,即引用。

      引入const后,引用有了一些有趣的规则,这里讲一下。

      const引用:const引用是指向const对象的引用,例如:

        const int r = 100;    
        double r1 = 100.0;
        const int &p1 = r;      //正确,const引用可以绑定到const对象上
        const int &p2 = r1;     //正确,const引用可以绑定到数据类型相关的const对象上
        const int &p3 = 100;    //正确,const引用可以绑定到右值

        与之对应的,非const的引用只能绑定到与该引用相同类型的对象上。

    3、指针与const

      同样简单先复习一下指针的知识。指针也是一种变量,它保存的是一个对象的地址(注意:指针也有自身的地址,该地址中的数据就是该指针指向的地址)。

      指针与const关系比较复杂,我这里借鉴《C++ Primer》上的顺序,非3小点来解释这个问题。

      1)指向const对象的指针

      我们知道,指针可以用来修改它所指向的对象的数据。但是如果它指向一个const对象,那么自然不允许被修改。C++语言中强制要求:指向const对象的指针必须具有const特性。

      for example:

         const double *pt;    //a point to a double that is const

      这里的pt是指向一个const对象的指针。值得注意的是,这里仅仅说明了这个指针指向的数据类型,而没有说这个指针本身就是const,因此定义的时候也不一定要初始化,同理如果有必要,还能在接下来的代码中将pt指向其他的const对象。指针本身是const会在接下来的几点中讲到。

      这个规则对void指针也成立,即:必须使用const void*类型的指针保存const对象的地址

          但是,C++允许把非const对象的地址赋给指向const对象的指针,例如:

        double  dval = 3.14;
        const double *pt = &dval;

      这样一来,不能通过指针pt来修改dval,但是仍然可以直接修改dval。

      《C++ Primer》上有句话也许可以用来帮助记忆这个“指向const对象的指针”:这种指针可以理解为“自以为指向const的指针”

      2)const指针

      上一点中,指向const对象的指针不能说明指针本身就是const,那么const指针就是说:指针本身就是const的,不能用它来指向初始化对象以外的对象

      const指针语法格式:

        int  errNumb = 0;
        int *const curErr = &errNumb;

         可以看到,这种指针必须初始化。但是同样的,const指针并没有说明:能否使用该指针来修改它指向的对象的值。能否修改取决于该对象的类型。

      3)指向const对象的const指针

      有了前两点的铺垫,这种指针就很好理解了。

        const double pi = 3.14159;
        const double *const pt = π

      这里,pt既不能修改pi的值,也不能更改pi的指向。我们可以从左到右阅读上述的声明语句:

             pt首先是一个const指针,指向double类型的const对象

         P.S 在《C++ Primer》上有这么一个例子值得讨论,这里拿来讲下。假设有下面的句子:

        typedef string *pstr;
        const pstr cstr;

      问这里的csr变量是什么类型的。很多人看到这里,都会认为第二句是这么展开的 const string *cstr; 因此它就是一个指向string类型的const对象的指针。这其实是错误的认识,这种错误源自于认为typedef单纯的是做文本扩展了(文本扩展那是宏定义的事)。这里应该这么理解:

      const修饰的是pstr类型,而pstr是什么类型呢?typedef告诉我们它是一种string*,就是指向string类型的指针,那么这里的cstr就是一种指向string类型的对象的const指针。即第二句应该这么还原: string *const cstr; 

      这里同时也是告诉我们,typedef做的事情是对类型的提升

    4、函数与const

      有了前面3点的铺垫,函数的const就很好理解了,直接举个例子吧

        const int  func(const int &a) const{
                  ...
        }

      函数返回一个const对象,他的参数是一个const的引用,它是一个const的常量函数,也就是说,该函数不会修改调用函数的实参。

     5、后记

      今天刚好遇到一个const常量成员函数的问题,不妨贴上来和大家分享下。

      错误代码是这样的,有兴趣的可以拿回去编译下。

     1 #include<iostream>
     2 using namespace std;
     3 
     4 class Point3d{
     5     public:
     6         Point3d(float x=0.0, float y=0.0,float z=0.0)
     7             :_x(x), _y(y), _z(z){}
     8             
     9         float x() {return _x;}
    10         float y() {return _y;}
    11         float z() {return _z;}
    12     private:
    13         float _x,_y,_z;
    14 };
    15 
    16 inline ostream&
    17 operator<<(ostream &os, const Point3d &pt){
    18     return os<<"("<<pt.x() << "," <<pt.y() <<"," <<pt.z() << ")"; 
    19     
    20 }
    21 
    22 int main(){
    23     Point3d pd(1,2,3);
    24     cout<<pd;
    25 }

      我使用DEV给我报的错的这样的:

      

     也就是说:

        不能将“this”指针从“const Point3d”转换为“Point3d &”----转换丢失限定符

     简而言之,第17行重载的<<操作符使用了const Point3d对象,那么const对象必须调用const成员函数,于是我的x(),y(),z()都没有声明成const函数,于是报错。

     在这里我们把每个函数填上const限定符就能解决了。

  • 相关阅读:
    【转】嵌入式软件:C语言编码规范
    【转】如何建立编码规范?
    RAS使用拨号网络拨号的类
    UDP 通讯代码
    【转】heap与stack的区别
    关于textarea在safari chrome下可拖动大小的问题
    Java网络编程入门
    诺基亚发布了它的第一台android手机,x和x+机型
    Spring学习笔记之入门(二)
    Spring学习笔记之入门(一)
  • 原文地址:https://www.cnblogs.com/HolyShine/p/6047082.html
Copyright © 2011-2022 走看看