zoukankan      html  css  js  c++  java
  • C++ const学习

    概念

      const就是为了直接表达“不变化的值”这一概念。也就是说该值只可读,不可直接写。
      由于不可以修改,所以const常量在声明的时候必须初始化

        const int a;    //error
        extern    const int ext_a;

    作用

    •  可以定义const常量,具有不可变性 
          const int a = 4 ;
          //a = 5;      //error
    • 便于类型检查,使编译器对处理内容有更多了解
      如 a = 5 在编译的时候可以将对const常量进行修改的部分检查出来
    • 保护被修饰的内容
      我们一直在建议不要修改函数的参数值,便于调试、维护,以及减少不必要的错误,但函数的调用者与函数的编写者,所以无法人为的保证传入的参数无法被修改,此时就运用const,运用编译器对代码进行检查。主要还是和引用参数联合使用,如果只是修改参数对调用者没影响还好说,否则...(后续详谈)
      void fun1(const int a)
      {
          //a=5;
      }
      
      void fun2(const ClassA& a)
      {
          //a.xx=xx 
      }
    • 提高代码的可读性、维护性
      运用const常量替换代码中出现的比较多的各种文字量,个人认为代码中出现数字0、1,阅读时还能理解,但是要是突然出来一个2、5、8,这是什么意思呢?可能自己写的代码过一阵子自己也不清楚了,此时我们就可以运用const常量或enum起一个合适的名字替代这些不易理解的数字。如果是字符串的话就只能运用const了,呃,或者是宏#define(个人不太喜欢宏,原因1.宏易出错,不易理解;2.编译器无法检查类型;3.C++不建议使用宏)
    • 函数重载
      两个重载函数必须在下列一个或两个方面有所区别:
      1、参数数量不同
      2、参数类型不同
        如下 funA以上两个方面都不满足,但是却可以重载,const函数对应const对象使用(后续详谈)
    • class ClassA
      {
      public:
          void funA()
          {
         //... }
      void funA() const { //... } }; 

     const与指针

      The C++ Programming Language里面给出过一个助记的方法:  把一个声明从右向左读。

        char * const p1;          //p1 is a const pointer to char
        const char *p2;            //p2 is a pointer to const char
        const char * const p3;    //p3 is a const pointer to const char

      Effective C++同样给出了一种方式,如果关键字const在星号的左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在两边,表示被指物和指针二者都是常量。其实指针只要分清指针本身与所指向的内容即可。个人觉得不用纠结与有些书上的叫法什么“指针常量”,“常量指针”,这都是在翻译的过程中带来的歧义。

      如p1是一个const pointer,所以在声明的时候必须初始化,否则编译不通过,而*p1则是char类型。
      p2是一个pointer但不是const,*P2才是const类型,所以p2可以不用初始化。

      那么p1声明指向的为char 是否可以指向const char 呢?p2声明指向的为const char 是否可以指向char类型呢?

        const char ca = 'a' ;
        char b= 'b';
    
        char *p;
        //p=&ca;                //error
        p=&b;
        char * const p1=&b;
        //char * const p1=&ca;        //error    
        const char *p2;
        p2=&ca;
        p2=&b;                        //ok
        const char * const p3=&b;    //ok

      因为对承诺不修改的内容要被修改,肯定是有问题的;但对可修改的内容不做修改没有任何问题。如上面ca不可修改,*p可以修改,所以p=&ca错误;而b可以修改,*p1不可以修改,p=&b对b不会造成不良影响,所以可以通过。

      那么是不是非const类型可以直接赋值与const类型呢?而const类型不能直接赋值与非const类型呢?

        ClassA ca;
        const ClassA cst_b;
    
        ClassA cc=cst_b;    //copy构造函数可以理解
        ClassA c2;
        c2=cst_b;            //??
        const ClassA cst_d=ca;     
    
        int a=1;
        const int b=a;
        int c=b;            //??

      以上代码完全可以编译通过,那该怎么解释呢?个人理解为如果赋值后的对象不对原对象代码不良影响,都是可以通过的。如int c=b;c的修改不会修改b;c2=cst_b,调用ClassA的赋值操作ClassA& operator=(const ClassA&),也同样不会对原cst_b修改。

     const与引用

       引用与指针有所不同,因为引用本身可以看作是一个常量指针,引用在声明是必须初始化,且不可以在引用值其他对象。所以引用只存在一种形式。const type& 而type& 与type& const 等价。const 引用主要运用在函数的参数传递方面。Effective C++ 第20条 Perfer pass-by-reference-to-const to pass-by-value.

        int a;
        int & ref1=a;
        const int & ref2 =a;
        int & const ref3=a;        //没必要

    const与函数

       函数与const 的关系可以从三部分来看,返回值、参数、函数自身

    • const修饰返回值
      class ClassA
      {
      public:
          int a;
      
          ClassA():a(1)
          {
          }
          const int funA()   //没意义,因为返回值本身就无法修改 与int funA()一样,而且也不存在funA()=4这种写法
          {
              return a;    
          }
          int * const funB() //与funA一样,const的限定的是返回值的指针,也无法修改 。与int *  funB() 一样
          {
              return &a;
          }
          const int * funC() //const修饰的是返回指针所指内容,所以该函数的接收这也必须为const int*类型
          {                        
              return &a;
          }
          const int &funD()   //返回引用,该引用不可以修改
          {
              return a;
          }
          void test()
          {
              int re=funA();
              int *p=    funB();
      
              //int *p1=funC();        //error
              const int *p2=funC();
      
              //int& c=funD();         //error
              const int& a2=funD();
               
          }
      };

       funA、funB其实实际意义都不大,因为不论返回值是不是const类型,函数调用者都不可能修改返回值的实际值。而函数调用者该不该用const与函数本身没关系。
      cosnt自定义类型返回值,往往可以降低因函数调用者错误而造成的以外,而又不至于放弃安全性和高效性

      ClassA funCA()
      {
          ClassA a;
          return a;
      }
      
      int _tmain(int argc, _TCHAR* argv[])
      {
          ClassA ca;
          funCA()=ca;
      }
        funCA()=ca;这句话具体有什么实际意义呢?没意义,但是就是可以编译通过,此时就可以将funCA返回值限定为const ClassA,这样的写法首先编译器都不通过。
    • const修饰函数参数
        Effective C++ 至于const参数,没什么特别新颖的观念,它们不过就像local const对象一样,你应该在必要使用它们的时候使用它们。除非你有需要修改参数或者loacl对象,否则请将他们声明为const。
          int funA(const int a);
          int funB(int * const p);
          int funC(const int *p);
          int funD(const int& ra);
    • const修饰成员函数自身
      将const实施于成员函数的目的,是为了确认该成员函数可以作用与const对象身上。这类函数有两个理由显得重要
      1.是class接口比较容易被理解。2.const对象使用
      class ClassA
      {
      
      public:
          int a;
      
          ClassA():a(1)
          {
          }
      
          void fun()
          {
              a=5;
              cout<<"this is not a const function"<<endl;
          }
          void fun() const
          {
              //    a=5;    //error
              cout<<"this is a const function"<<endl;
          }
      };
      int _tmain(int argc, _TCHAR* argv[])
      {
      
          ClassA ca;
          ca.fun();    //this is not a const function
      
          const ClassA cb;
          cb.fun();    //this is a const function
      }

      const对象只能调用const函数,且const函数不能对成员函数做修改。若将void fun()函数删掉,则编译不通过错误提示:ClassA::fun”: 不能将“this”指针从“const ClassA”转换为“ClassA &;若将void fun() const 函数删掉,则ca.fun()调用const fun。

       今天快下班了,先写这些吧,明天补充总结!

  • 相关阅读:
    centos7 安装配置openstack-dashboard (官网openstack-juno版)
    OpenCV图像处理篇之图像平滑
    在matlab中生成m序列
    【转】oracle创建表空间
    Android代码中动态设置图片的大小(自动缩放),位置
    Eclipse安装SVN插件
    visualSVN server库迁移
    Win7 64bit 安装VisualSVN出现报错:Servic 'VisualSVN Server' failed to start.解决办法
    具体图解 Flume介绍、安装配置
    hadoop(八)
  • 原文地址:https://www.cnblogs.com/haox/p/3177726.html
Copyright © 2011-2022 走看看