const和指针

const位于数据类型的前面

根据有无const应用于变量和指针,两两组合可以有4种情况,分别:

  • 常规变量的地址赋值给常规指针
  • 常规变量的地址赋值给指向const的指针
  • const变量的地址赋值给指向const的指针
  • const变量的地址赋值给常规指针(不被允许)
  1. 常规变量的地址赋值给常规指针
    最常用的一种形式,没有const作用

  2. 常规变量的地址赋值给指向const的指针

    1
    2
    int age =39;
    const int* pt = &age;

    上述声明指出,pt指向一个const int类型的值(age=39),*pt的值为const,不能修改,即不能使用pt来修改age。

    1
    *pt += 1;//invalid,因为pt指向一个const int

    但是pt的声明并不意味着pt指向的值是一个常量,只是意味着对于pt来说这个值是常量。例如,pt指向age,而age并不是const,因此可以直接通过age变量来修改age的值,然而却不能使用pt指针来修改age.

    1
    2
    *pt = 20;//invalid,因为pt指向一个const int
    age = 20;//valid,因为age并不是const

    多说一点:
    上述声明中,const只能防止修改pt指向的值(正如上述演示的一样),而不能防止修改pt本身的值,也就是说可以讲一个新地址赋值给pt

    1
    2
    int sage = 80;
    pt = &sage;//invalid

    但是仍然不能通过pt来修改他新指向的值(即sage的值80)。

    这就好像是pt通过媒人age 爱上了39这个数。pt以为39是恒定不变的,却不知道媒人age可以让39变成任何数。
    对pt来说,很明显39对自己不感兴趣,既然改变不了39,那就改变自己。于是他又通过新媒人sage,介绍了个新对象80,可是pt仍然以为80是恒定不变的,殊不知sage可以让80变成任何数。

  3. const变量的地址赋值给指向const的指针

    1
    2
    const float g_earth = 9.80;
    const float* pe = &g_earth;

    上述声明,g_earth是一个const float类型的变量,pe是指向const float的,因此不能使用pe修改这个值,也不能使用g_eatth修改这个值

  4. const变量的地址赋值给常规指针(不被允许)
    注意:这是不被允许的,下面给出一个解释

    1
    2
    const float g_earth = 9.80;
    float* pe = &g_earth;//invalid

    如果可以通过pe的值修改g_earth的话,那么之前把g_earth声明为const float则显得没必要了,因此c++禁止这种做法

const位于数据类型的后面

与上述不同的是,关键字const的位置位于数据类型的后面,而且看着比较别扭

  1. 例子1

    1
    2
    3
    int sloth = 3;
    const int* ps = &sloth;//ps 指向 const int
    int* const finger = &sloth;//const figer 指向 int

    上述声明中,figer只能指向sloth,但是允许使用finger来修改sloth的值。不允许ps修改sloth的值,但是允许ps指向另一个位置。
    简而言之:finger*psconst,而*figerps不是.细细体会!

  2. 例子2–声明指向const对象的const指针

    1
    2
    double troble = 2.00;
    const double* const stick = &troble;

    上述声名中,stick不能修改trouble的值,且stick只能指向troule。前者由前一个const作用,后者由后一个const作用

通过const将指针与引用联系起来

引用更接近与const指针,一旦与某个变量关联起来,就一直效忠于它

  1. 例子
    1
    2
    3
    int rats;
    int &rodents = rats;
    int* const pr &rats;
    实际上上面代码是下面的伪装,引用rodents扮演的角色和*pr相同