可不能小瞧了 const

来源:互联网 发布:php爱奇艺vip解析源码 编辑:程序博客网 时间:2024/05/10 17:35

有的时候我们需要在程序中使用这么一种一种变量,希望他们的值在定义了之后就不会在改变了,于是就有了 const 这个修饰符,也正因为用 const 修饰的变量的值不可以被修改,所以在定义的时候就要求必须给予初值。
当一个指针或引用和 const 结合时会发生很多美妙的事情,嘿嘿。我们知道指针是一个对象,但引用不是(这里也有很多有趣的问题),指针可以指向另外一个对象,这时指针本身是不是常量和指针所指的那个对象是不是常量就是一个值得思考的问题。我们可以把 const 细分为顶层 const (top level const ,和指针结合时用来表示指针本身是一个常量),和底层 const (low level const ,和指针结合时用来表示指针所指的对象是一个常量)。顶层 const 可以表示常量对象,而底层 const 则是修饰指针或引用时产生的一种现象。

int num = 1;int *const ptr = #            // 定义了一个顶层 const ,ptr 的值不可以被改变const int *ptr1 = #           // 定义了一个底层 const ,ptr1 的值可以被修改const int *const ptr2 = &num      // *号左边的是底层 const, *号右边的是顶层 constconst int &r = num;               // 修饰引用的 const 都是底层 const

发生拷贝时,顶层和底层 const 会有很大的区别,顶层 const 往往不会影响赋值,因为,把一个常量对象赋给一个普通对象时,只是把常量对象的值拷贝了一份给普通对象,对普通对象的操作并不会影响到常量对象,而把一个普通对象赋给一个常量对象时,更是没有问题,普通对象也只是把它的值拷贝了一份给常量对象,只是常量对象自己限制自己的值不可被改变而已,比如

const int num1 = num;           // 可以用普通对象来初始化一个顶层 const 的对象num = num1;                      // 可以把一个顶层 const 的值赋给一个普通对象// 但是,当变量具有底层 const 属性时就不一样了,比如int *ptr3 = ptr1;                // 非法,ptr1 具有底层 const 属性,而 ptr3 没有,我们也可以自然的想到,                                 // 如果可以的话,那么就可以通过 ptr3 修改 ptr1 指向的对象了,但是 ptr1 认为自己指向                                 // 的是一个常量对象,这样会局面会混乱,所以编译器拒绝这样的写法也是合理的。ptr1 = ptr2;                     // 正常,ptr2 和 ptr1 都具有底层 const 属性,而 ptr2 的顶层 const 会被忽略 

还有当用一个具有顶层 const 属性的对象去初始化一个 auto 推导出的类型时,对象的顶层 const 属性会被忽略掉。但是定义一个 auto 类型的引用时,推导出来的类型仍然具有顶层 const 属性。decltype 的作用和 auto 差不多,但是用法上有些不同。decltype 遇到顶层 const 和引用时得到的结果与 auto 有所不同,如果 decltype 内的表达式是一个变量,decltype 推导出的类型会包括该变量的顶层 const 属性和引用。

const int kNum = 0, &r = kNum;auto a = kNum;                   // a 为 int 类型,kNum 的顶层 const 属性被忽略auto &b = kNum;                  // b 为 const int & 类型,kNum 的顶层 const 属性被保留auto c = r;                      // 这样的写法并不能得到引用类型,r 是 kNum 的一个别名,这里会按照 kNum 来推导类型,所以得到的还是 int 类型decltype(kNum) d = 0;            // d 为 const int 类型decltype(r)    e = d;            // e 为 const int & 类型
阅读全文
0 0
原创粉丝点击