const关键字对C++成员函数的修饰

const对C++成员函数的修饰分为三种:1. 修饰参数;2. 修饰返回值;3. 修饰this指针。简述一下知识点如下,以后找功夫再完善。

1. 对函数参数的修饰。

  1)const只能用来修饰输入参数。输出型参数不能用const来修饰。

  2)如果输入参数采用“指针传递”,那么加const修饰可以防止意外地改动该指针,起到保护作用。

  3)如果输入参数采用“值传递”,函数将产生临时变量(局部变量),复制该参数的值并且压入函数栈。函数中使用该参数时,访问的是函数栈中临时变量的值,原变量无需保护,所以不要加const修饰。

  4)基本变量类型的参数作为“值传递”的输入参数,无需采用引用。自定义变量类型(class类型,struct类型)参数作为“值传递”的输入参数,最好采用"const+引用"格式,即 void func(const A& a)。原因是自定义变量类型作为值传递时,设计创建临时变量,构造,复制,析构,这些过程很消耗时间。

  从函数栈的基本原理考虑原因。我们知道,函数在被调用时,会为创建各个实参创建临时变量并将其压入函数栈。如果是基本变量类型,则压入函数栈的临时变量中存储的是实参的副本;如果是自定义变量类型,则会在堆上创建该类型实例,复制该实参到堆上,然后将堆上该实例的地址压入函数栈;如果是指针,则会将指针地址的副本(其实也可以认为这个保存这个指针的变量是基本变量类型)压入函数栈。

  也就是说,函数栈上要么保存的是一个基本类型参数的副本,要么是个顶层指针。对于函数栈上保存的参数,实参的副本可以作为一个普通的局部变量,是可以修改值的,而对于指针变量,其可以视为顶层指针,本身的值不可以修改,但其指向的值可以修改。

  故而可知,对于基本变量类型,函数内部操作的是函数栈上的副本,不会对原值产生影响,对于类类型(非指针输入性参数),操作的也是函数栈上的地址指向的实例副本,同样不会对原值产生影响;而对于指针,函数内部虽然改变不了指针变量保存的指针值(该指针为顶层指针),但该指针却指向的是原值的地址,故而能修改原值。

  对于引用,a)引用只是变量的一个别名,引用指向元变量内存地址,不会进行新的内存分配和变量的拷贝;b)引用声明后必须马上初始化;c)引用一经定义,不能改变其值,也就是不能再作为其它变量的引用; d)通过引用可以完全操作原变量。

  可以看出,当占空间很大的变量作为输入型实参时,很适合用引用传递。因为用引用传递时,只是传递变量本身的一个别名,不会进行新变量的内存分配,构造,赋值,析构等操作。

  如果函数中不允许改变该实参,那么就应该在引用参数上加const修饰。

  基于上述考虑。const修饰输入型参数时,只需要修饰指针类型和引用类型即可(虽然不是强制,但对于输入型指针或者引用参数用指针修饰应该成为一种习惯)。

  同时,这也说明一个编程时应该养成的习惯,对于输入型参数,应该在函数起始位置定义一个局部变量接收该输入型参数,而不是直接使用。

 2.  对返回值的修饰。

  这个应用比较少。大部分返回值采用的时“值传递”。如果将返回值修饰为const,那么接收返回值的变量也必须定义为const。

 3. 对this指针的修饰。

  我们知道,c++成员函数在编译时候,会传入一个this指针,指向实例本身。这个this指针默认实际上是个顶层指针。即如果有classA,那么这个指针其实类似如下的定义:

  classA * const this;

  即this指针指向实例本身并且不可以修改,但可以通过this指针修改其指向的成员变量。在成员函数内访问成员变量m_var,实际上时如下形式方位的:

  this.m_var;

  如果我们设计一个成员函数时,不想让其修改成员变量,那么就应该将this指针定义为底层指针。c++定义的方式就是在函数签名后面加上const,即

  void func(const A& a, int b, const int* c, int* d)const;

  显然,上述成员函数中,a为const引用传递,不可以改变原值;b为值传递;c为const指针传递,不可改变原值;d为输出参数,可以改变原值。而该函数为const成员函数,不可以修改成员变量值。

  以下是const成员函数注意的几点

  1)const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.即对于class A,有

  const A a;

  那么a只能访问A的const成员函数。而对于:

  A b;

  b可以访问任何成员函数。

  2)const对象的成员变量不可以修改。

  3)mutable修饰的成员变量,在任何情况下都可以修改。也就是说,const成员函数也可以修改mutable修饰的成员变量。c++很shit的地方就是mutable和friendly这样的特性,很乱。

  4)const成员函数可以访问const成员变量和非const成员变量,但不能修改任何变量。检查发生在编译时。

  5)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员。

  6)const成员函数只是用于非静态成员函数,不能用于静态成员函数。

  7)const成员函数的const修饰不仅在函数声明中要加(包括内联函数),在类外定义出也要加。

  8)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const 成员函数。

原文地址:https://www.cnblogs.com/myseasky/p/7458064.html