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 成员函数。

const关键字对C++成员函数的修饰的更多相关文章

  1. 用 const 限定类的成员函数

    类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于 ...

  2. const用在成员函数之后的情况

    常成员函数         使用const关键字进行说明的成员函数,称为常成员函数.只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象.常成员函数说明格式 ...

  3. C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!

    之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点.知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自 ...

  4. const成员函数和mutable关键字

    一.const成员函数 class MyClass { public: void fun() const { } private: int m_nValue; } const成员函数内不能修改成员变量 ...

  5. const 修饰成员函数 前后用法(effective c++ 03)

    目录 const在函数后面 const修饰成员函数的两个作用 const在函数前面 总结 const在函数后面 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态 ...

  6. 第24课.经典问题解析(1.析构函数的顺序;2.const修饰对象;3.成员函数,成员变量是否属于具体对象)

    1.当程序中存在多个对象的时候,如何确定这些对象的析构顺序? 单个对象 单个对象创建时构造函数的调用顺序 a.调用父类的构造函数 b.调用成员变量的构造函数(调用顺序与声明顺序相同) c.调用类自身的 ...

  7. 类中用const限定的成员函数

    本文转自http://blog.csdn.net/whyglinux/article/details/602329 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非 ...

  8. (转)函数后面加const--C++ const成员函数

    类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于 ...

  9. C++之const类成员变量,const成员函数

    const修饰类的成员函数 const修饰变量一般有两种方式:const T *a,或者 T const *a,这两者都是一样的,主要看const位于*的左边还是右边,这里不再赘述,主要来看一下当co ...

随机推荐

  1. 数字签名中公钥和私钥是什么?对称加密与非对称加密,以及RSA的原理

    http://baijiahao.baidu.com/s?id=1581684919791448393&wfr=spider&for=pc https://blog.csdn.net/ ...

  2. 用 mongodb 储存多态消息/提醒类数据(转)

    原文:http://codecampo.com/topics/66 前天看到 javaeye 计划采用mongoDB实现网站全站消息系统,很有同感,mongodb 很适合储存消息类数据.之前讨论了如何 ...

  3. ERROR 2002 (HY000): Can't connect to local MySQL server through socket

    原文链接:https://blog.csdn.net/u011262253/article/details/82802157 一.错误现场还原: 下面我们通过三种方式来连接,然后观察提示的错误信息: ...

  4. C# 反双曲余弦函数

    反双曲余弦函数的定义是: T1 = Math.Log(t + Math.Sqrt(t * t - 1)); 1. 叉乘(cross product),也叫向量的外积.向量积.顾名思义,求下来的结果是一 ...

  5. HDU2426:Interesting Housing Problem(还没过,貌似入门题)

    #include <iostream> #include <queue> #include <stdio.h> #include <string.h> ...

  6. JQuery表格操作的常用技巧总结

    JQuery对表格进行操作的常用技巧. 1.表格奇数行和偶数行分别添加样式 复制代码代码如下: $(function(){  $('tr:odd').addClass("odd") ...

  7. 后台管理系统-使用AdminLTE搭建前端

    返回总目录<ABP项目实战-后台管理系统-目录> 安装AdminLte 我们通过Nuget包管理器安装AdminLte 引用三方组件 因为AdminLte使用到了很多三方的组件,所以我们需 ...

  8. P1351 联合权值(树形dp)

    P1351 联合权值 想刷道水题还交了3次.....丢人 (1.没想到有两个点都是儿子的状况 2.到处乱%(大雾)) 先dfs一遍处理出父亲$fa[x]$ 蓝后再一遍dfs,搞搞就出来了. #incl ...

  9. CSS 分页实例

    CSS 分页实例 一.简单分页 如果你的网站有很多个页面,你就需要使用分页来为每个页面做导航. 以下实例演示了如何使用 HTML 和 CSS 来创建分页: <!DOCTYPE html> ...

  10. MySQL "Zero date value prohibited" 问题解析

    问题起因 之前一直使用Oracle数据,对MySQL数据库使用不多,因此搞不懂MySQL的日期“0000-00-00 00:00:00”对程序会产生怎样的影响.费了我一下午的时间 -_-^^. 首先: ...