码迷,mamicode.com
首页 > 编程语言 > 详细

C++ const关键字

时间:2017-11-15 00:28:35      阅读:26      评论:0      收藏:0      [点我收藏+]

标签:strong   就是   调用   span   size   div   font   代码   prime   

定义


 const关键字的作用是对变量的类型加以限定。被const修饰的变量值不可改变(初始化后不可以再被赋值),例如:

const int num1 = 1;
num1 = 1; //错误

const表示变量是不可写的,但是这并不影响变量的可读性:

const int num1 = 1;
int num2 = num1; //正确,可以使用常量对象进行拷贝初始化

const引用


 使用const修饰的引用称为对常量的引用,实际上是将引用绑定到一个常量对象上。

const int num1 = 1;
const int &r1 = num1; //正确,常量引用r1绑定到常量对象num1上

 需要注意的是,非常量引用不能绑定到常量对象上。这是因为可以通过非常量引用修改其绑定的对象,所以非常量引用只能绑定到非常量对象上。

const int num1 = 1;
int &r2 = num1; //错误,不能将非常量引用r2绑定到常量对象num1上

 虽然非常量引用不能绑定到常量对象上,但是常量引用却可以绑定到非常量对象上。

int num2 = 1;
const int &r1 = num2; //正确,常量引用r1绑定到非常量对象num2上

关于引用(常量、非常量)和对象(常量、非常量)的绑定关系,我们可以这样理解,引用只是一个别名,我们使用引用的目的是通过引用修改其绑定的对象,我们不会去修改常量引用绑定的对象,所以常量引用可以绑定到常量对象上,也可以绑定到非常量对象上;相反,非常量引用只能绑定到非常量对象上。

既然常量引用不会去修改其绑定的对象,那么直接将常量引用绑定到字面值或者一般表达式上也是可以的:

const int &r1 = 1; //正确,常量引用r1绑定的值是0

const指针


使用const修饰的指针称为常量指针,常量指针必须初始化,而且一旦初始化完成,它的值(存放在指针中的地址)就不能再改变了。

int num3 = 1;
int *const p1 = &num3; //p1将一直指向num3

需要注意的是,指针指针本身是一个常量并不意味着不能通过指针修改其所指的对象的值。

int num3 = 1;
int *const p1 = &num3; //p1将一直指向num3
*p1 = 2; //此句结束后num3的值变为2

那么,如何使得指针所指对象的值不能修改呢?只要使用const修饰对象即可,此时指针的定义语句前面也要加上const:

const int num4 = 1;
const int *const p2 = &num4; //p2将一直指向num4
*p2 = 2; //错误,不能修改num4的值
num4 = 2; //错误,不能修改num4的值

上面代码中p2的定义语句中出现了两个const,这两个const的含义是不同的,第一个const表示指针指向的对象的值是不可修改的,第二个const表示指针本身(指针也是对象,它的值就是它存储的地址值)是不可修改的。这两个const的不同含义就是下面要讲的顶层const和底层const。

顶层const和底层const


顶层const表示指针本身是一个常量,即指针一直指向一个对象。

底层const表示指针所指的对象是一个常量,即指针所指的对象是不可修改的。

int num4 = 1;
int *const p2 = &num4; //顶层const
const int *p3 = &num4; //底层const
const int *const p4 = &num4; //既是顶层const,又是底层const

引用可以看作是底层const,和引用一样,不能将一个非底层const指针指向常量对象:

const int num5 = 1;
int *p5 = &num5; //错误,不能将非底层const指针p5指向常量对象num5
int *const  p6 = &num5; //错误,不能将非底层const指针p6指向常量对象num5

const成员函数


在C++类的定义中,可以在成员函数的参数列表后加上const,const的作用是修改隐式this指针的类型。

何为隐式this指针?我们通过对象调用成员函数时,成员函数如何知道是哪一个对象对其的调用呢?实际上,成员函数会包含一个名为this的额外的隐式参数,当我们调用一个成员函数时,成员函数会用请求该函数的对象地址初始化this。我们来看下面的代码:

class Person
{
   private:
         int height = 170;
         int weight = 60;
   public:
         int getHeight() //普通成员函数
         {
              return height; //相当于return this.height;
         }
         int getWeight() const //const成员函数
         {
              return weight; //相当于return this.weight;
         }
};
Person person1;
int h1 = person1.getHeight(); //正确,此时会将person1的地址隐式赋给getHeight函数的隐式参数this
int w1 = person1.getWeight(); //正确
const Person person2;
int h2 = person2.getHeight(); //错误,不能在一个常量对象上调用一个普通的成员函数
int w2 = person2.getWeight(); //正确

对象一旦创建,this就会一直指向这个对象,所以其实this是一个常量指针(顶层const)。

this默认情况下是一个顶层const(Person *const this),下面的代码演示了person1和person2调用getHeight函数时的隐式初始化语句。

//下面用p1表示person1的指针,p2表示person2的指针
Person *const this = Person *p1; //person1调用getHeight函数,正确
Person *const this = const Person *p2; //person2调用getHeight函数,错误

常量对象person2调用普通成员函数getHeight时,隐式初始化语句企图将一个常量对象赋给一个非常量对象(底层),所以会引发错误。在这种情况下,如果this指针是底层const,我们的初始化语句就没问题,const成员函数的作用就在此。下面的代码演示了person1和person2调用getWeight函数时的隐式初始化语句。

//下面用p1表示person1的指针,p2表示person2的指针
const Person *const this = Person *p1; //person1调用getWeight函数,正确
const Person *const this = const Person *p2; //person2调用getWeight函数,正确

 总结


  1. 被const修饰的变量值不可写,但是可读;
  2. 无论是引用还是指针,非常量可以向常量转换,但反之不可,即常量引用/指针可以指向非常量对象,而非常量引用/指针不可以指向常量对象;
  3. 顶层const是指指针本身不可变,底层const是指指针指向的对象不可变;
  4. const成员函数中的const可以修改隐式this指针的类型。

参考文献


《C++ Primer》第5版

 

C++ const关键字

标签:strong   就是   调用   span   size   div   font   代码   prime   

(0)
(0)
   
举报
评论 一句话评论(0
0条  
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!