用const修饰"记忆变量"。。。

C++的const用法真NND复杂,花时间梳理一下,记录下来,记备后用。若有误解,欢迎拍砖!


1. const变量

  const int val = 512;

  常量在定义后不能被修改,所以定义时必须初始化(相信大家都知道).

  const对象默认为文件的局部变量,即其作用域是定义该对象的文件,不能被其它文件访问(定义在所有函数外的名字具有全局作用域,即可在程序的任何地方访问).

  通过指定const变量为extern,就可以在整个程序中访问const对象:

  extern const int val = 512;

2. const引用

  const引用是指向const对象的引用!

  const int ival = 1024;

  const int &refVal = ival;   // ok:  both reference and object are const

  int &ref = ival;         // error: nonconst reference to a const object

  const引用可以初始化为不同类型的对象或者初始化为右值,如字面常量:

  int i = 42;

      //legal for const reference only

      const int &r = 42;

      const int &r2 = r+i;

      然而对非const引用却是不合法的,会导致编译错误:

  int &refVal = 10                     // error: initializer must be an object

      观察下述代码:

  double dval = 3.14;

      const int &ri = dval;

      编译器会把这些代码转换成以下代码:

  int temp = dval;                     // create temporary int from the double

      const int &ri = temp;              // bind ri to that temporary

      这样给ri赋值并不会修改dval,而只是修改了temp,因为const引用是只读的!

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

  const引用则可以绑定到不同但相关的类型的对象或绑定到右值。

*3. 指针和const

      3.1 指向const对象的指针

  不允许用指针来改变所指的const值。C++强制要求指针也必须有const特性(类似于上边的const引用):

  const double *cptr;                // cptr may point to a double that is const

      cptr本身并不是const,可以修改,只是指向了一个const对象。定义时的初始化是非必须的(因为它实质并非一个const对象)。

      若该指针指向的是一个非const对象,则可以直接修改对象值。指向const的指针不能保证所指向的值一定不可修改。

  3.2 const指针

  指针本身的值不可修改,且必须在定义时初始化:

      int num = 0;

      int *const cptr = #

      可以用指针修改对象的值。

      3.3 指向const对象的const指针

  即不能修改指针所指向对象的值,也不允许修改该指针的指向(即指针值):

      const double pi = 3.14;

      const double *const pi_ptr = π

      想必都清楚,第一个const修饰指针所指的对象,第二个const修饰指针本身。


*4. 函数与const

  4.1 参数const

      若函数是值传递的,const参数限定就失去了意义,因为值传递本身不会改变被传入的值,而只是传递了变量或对象的一个副本。

  然而对于引用或指针传递,由于其会直接改变传入的值,这时使用const就显得格外重要。

  PS:在<<Effective C++>>一书中讲到:对于内置类型,用值传递会比引用传递效率来得高,而对于对象或用户定义类型,使用引用(并且是const引用)效率更高,并且可以免去切割问题。

  4.2 返回值与const

      对于内部数据类型来说,返回值是否const没有意义。处理用户定义的类型时,如果返回类对象的值,则const是非常重要的,因为返回值不能为左值(即不能被赋值,不能被修改)。

  返回值为的址时,是否用const修饰它,取决于用户想要做什么。

  PS:对于临时变量作为参数传递,有点意思:一个总是常量的临时变量(编译器使然),它的地址可以被传递给一个函数。临时变量通过引用被传递给一个函数时,这个函数的参数一定是常量引用。下面的例子说明了这一点:

  class X {};

      X  f() {return X();}                //return by value

      void g1(X &) {}                    // Pass by non-const reference

      void g2(const X&) {}           // pass by const reference


      main(){

              g1(f());                      // Error: const temporary created by f()

              g2(f());                      // OK

      }

5. 类与const

      5.1 类里的const成员

      这里有两方面意思:

  (1) 在一个对象生命周期内,这是一个常量。需用初始化表达式表初始化,如下例:

    class Fred {

                  const size;                      //just declaration, can't initialization

            public:

                  Fred();

                  Fred(int i);

            };

            Fred::Fred() : size(100){};

            Fred::Fred(int i) : size(i){};

      (2)  对整个类来说,这是一个常量(一个编译时常量)。需要用一个不带实例的无标记的enum,如下例:

    class Bunch {

                 enum {size = 100};                       //枚举常量在编译时被求值

                 int i[size];

            };

      5.2 const对象和成员函数

      一个类对象为const对象,即其数据成员在对象生命周期内不会被改变。

  要保证数据成员不被改变,就该const成员函数出场了!

  声明const成员函数,等于告诉编译器可以为一个const对象调用这个函数。一个非const成员函数被看成是将要修改对象中的数据成员,编译器不允许一个const成员调用非const成员函数。

  const成员函数不允许修改成员变量或者调用非const成员函数。将不会修改成员变量的成员函数声明为const,以便const对象调用。

  const成员函数的声明语法不再赘述,另外要说明一下,const成员不仅仅需要声明,定义时也需在函数参数列表后const关键字。

  其实说到底,const成员函数也是可以修改成员变量的,需理解按位与按成员const的概念,以及关键字mutable,困了不说了......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值