C++中的关键字const分析

在这里总结一下const可能并没有什么新的东西,只能说是一起来复习一下const。现总结const的主要作用如下(当然,应该还有很多吧):  
   
  1.             代替#define。  
   
  讲到用const来代替#define,为什么要这样做呢,当然是const比#define更好啦,一个很明显区别就是const有数据类型,可以进行类型安全检查,而#define只是简单的替换,并这个功能。所以我们就尽量使用  
   
            const   double   pi   =   3.1415926;  
   
  来代替这样的语句:  
   
            #define   pi   3.1415926;//最好用const来定义  
   
  而且#define的定义在进入编译器前会被替换掉,这样,当涉及到这个常量的编译错误时,报告是不是pi而是3.1415926这个常量,这样就带来的调试上的麻烦。  
   
  用cosnt来代替#define还有一个好处就是减少不必要的内存分配,例如:  
   
          #define   PI   3.1415926                   //常量宏  
   
          const   doulbe     Pi=3.1415926;     //此时并未将Pi放入ROM中  
   
          ......  
   
          double   i=Pi;                               //此时为Pi分配内存,以后不再分配!  
   
          double   I=PI;                               //编译期间进行宏替换,分配内存  
   
          double   j=Pi;                               //没有内存分配  
   
          double   J=PI;                               //再进行宏替换,又一次分配内存!  
   
  const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝换,又一次分配内存!(占用更多的内存)  
   
  2.       使某个对象(变量)、值,指针,引用不能被修改。  
   
                    相信这一点是大家最常见,用它来定义常量,使之具有不可变性。  
   
  对于用来修饰对象(变量),非常好理解,也是经常使用const的作用之一。但对于指针,可能就不好那好理解了,幸运的是Meyers大师给了我们一个很好的方法(在<<EC.Iitem21>>中)如果const在*号的左边,则说明数据是常量也就是指针所指向的那个对象为常量,如果const在*号的右边,则说明指针自身是一个常量,看看下的代码的解释:  
   
                    int   myvar   =   500;           
   
                   const   int*   p1   =   &myvar;   //指针p1可以被修改,但p1指针指向的值是不能被修改的。  
   
                  int   const   *p2   =   &myvar;     //(同语句const   int*   p1   =   myvar意思一样)。  
   
                 int*   const   p3   =   &myvar;//指针p3不能被修改,但p3指针指向的值是可以被修改的。  
   
                const   int*   const   p4   =   &myvar;         //指针p4和p4指针指向的值都不能被修改。  
   
                同样const可也用来修饰引用,加在数据类型前后都可以.  
   
                                      int   var1   ;  
   
                              double   var2   ;  
   
                              const   int   &r   =   var1;//r不能被修改,var1值可以修改 
   
                              double   const   &s   =   var2;//s不能被修改,var2值可以修改 
   
  3.       使类的静态对象在类内部可以初始化  
   
  当我们要在类的内部定义某个常量时,就可能用const来修饰,否则的话,就不能初始化,看看下面的代码  
   
  class   print  
   
  {  
   
            private:  
   
                                //不能写成static   int   count   =   10;  
   
  static   const   int   count   =   10;  
   
  string   info[count];  
   
  };  
   
  const   int   print::count;  
   
                    当然出也可以通过类构造函数的初始化成员列表来初始化cosnt常量:  
   
                                class   A  
   
                    {  
   
                                public:  
   
                                                              A(int   i=0):count(i)   {}  
   
                                  private:  
   
                                                            const   int   count;  
   
                      };  
   
  (题外话)当然,对于很久以前的编译器(1995年以前)是不认可这种代码的,当然要达到这种效果可以采用借助为menu来解决,代码像这样:  
   
                                      class   print  
   
  {  
   
                              menu{count   =   10   };//借助枚举来得到一个初始值  
   
                              string   info[count];  
   
  };        
   
  4.       修饰函数参数和返回值,对于类的成员函数可以确定不能修改类的数据成员.  
   
                    用const用修饰函数参数是一种常见的行为,见下面代码:  
   
                              const   bigint   operator+(const   bigint&   bigvar1,   const   bigint&   bigvar2)  
   
                              {         return     bigvar1.value+bigvar2.value;   }  
   
  由于bigvar1和bigvar2   都是类类型,为了提高传值的效率,所以就用对象的引用,但是这样就有一个问题,我们不能阻止在函数内部修改bigvar1和bigvar2的值,解决办法只能用const,这就是我们在非内部数据类型的函数参数传递中常用的一种”const引用传递”,它可得到高效率,同时阻止函数内部对对象进行修改。  
   
  再看看对象前面的const(bigint前面)       它的作用是不允许下面的代码存在:   (a+b)   =   c     //a,b,c都是bigint类型  
   
  上面的代码很显然是没有意义,它对一个运算结果进行赋值,我们就应该加上const来阻止这样的代码发生。      
   
  对于类的成员函数,若不会修改数据成员,我们都应该有const来声明,若我编写这样的函数时不小心修改了类的数据成员或调用非const的成员函数,编译器就会给予相关的提示。看看下面的代码:  
   
            class   myprint  
   
  {  
   
    public:  
   
                  myprint():printcount(0){};  
   
                  void   print();  
   
                  int   getcount()   const;  
   
    private:  
   
                    myprint(const   myprint&);  
   
                  myprint&   operator=(const   myprint&);  
   
                  int   printcount;  
   
  };  
   
  void   myprint::print(){}  
   
  int   myprint::getcount()   const  
   
  {  
   
        ++printcount;       //错误,以const成员函数不能修改类的数据成员  
   
        print();                         //错误,以const成员函数不能调用非const成员函数  
   
        return   printcount;  
   
  }  
   
  用const来修饰成员函数实际上修饰的是this指针,所以静态成员函数不能声明为const,原因很简单:静态成员函数没有this指针。这里要注意const成员函数中关键字const是放在成员函数的最后面。  
   
  有时候我的确要在const成员函数中修改类的内部数据员,这时应该怎么办呢,幸运的是标准c++提供的关键字mutable来达到,只要在类数据成员前加上关键字mutable:  
   
  class   myprint  
  {  
   
  public:  
   
  ……  
   
                              int   getcount()   const;  
   
                    private:  
   
                              ……  
   
                              mutable   int   printcount;  
   
  };  
   
  ……  
   
            int   myprint::getcount()   const  
   
  {  
   
                    ++printcount;//正确,因为printcount有关键字mutable修饰  
   
                              ……  
   
        return   printcount;  
   
  }  
   
  当然,还有其它方法(使用const_cast或通过指针间接来修改或通过成员函数的this指针)同样能达到修改的目的,但最好是用mutable。  
   
  5.       用const来修饰重载的类的成员函数。  
   
                    有时候我们要为类提供成员函数的const重载版本,以适应不同情况的需要,例如看看SGI   STL关于stack中的一段代码:  
   
            class   stack  
   
  {  
   
                      ……  
   
                    public:  
   
                                        reference   top()   {   return   _M_c.back();   }  
   
                                        const_reference   top()   const   {   return   _M_c.back();   }  
   
                                        ……  
   
  }  
   
  这里就为stack提供为返回栈顶值的两个版本。例如:  
   
            top   =   mystack.top()   //调用const_reference   top()   const  
   
  而下面的代码:  
   
            mystack.top()   =   myvar   //调用reference   top()  
   
  其实   const的作用应该不止上面说的那些,但可以说一些常用的功能都提到了。在合适使用cosnt的地方,应该尽量使,使程序变得简单,清晰.  
   
            最后,可以看看这个函数中所有const的意义:  
   
                    const   char*   const   foo(char   const   *   const   str)   const  
   
  第一个const表示返回类型为const,也就是不能把此函数的返回值当作左值来使用。  
   
  第二个const表示指针的不可变性,但在这是可以省略,因为返类型已经是const。  
   
  第三个cosnt表示str的常量性,也就其内容是不能改变,可以写在其前面的char的前面。  
   
  第四个cosnt表示str的指针的常量性,也就是此指针不能指向别的地址。  
   
  第五个cosnt表示此函数的常量性(前提是类的成员函数),不能修改所在类的数据成员。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值