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 成员函数。
const关键字对C++成员函数的修饰的更多相关文章
- 用 const 限定类的成员函数
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于 ...
- const用在成员函数之后的情况
常成员函数 使用const关键字进行说明的成员函数,称为常成员函数.只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象.常成员函数说明格式 ...
- C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!
之前一直在学习C/C++,关于const的使用,这里出现一点,那里出现一点.知识用时方恨少,这一段时间正好各种笔试题,其中关于const的用法也是层出不穷,所以疲于在书本上各种翻,这里汇总一下,加深自 ...
- const成员函数和mutable关键字
一.const成员函数 class MyClass { public: void fun() const { } private: int m_nValue; } const成员函数内不能修改成员变量 ...
- const 修饰成员函数 前后用法(effective c++ 03)
目录 const在函数后面 const修饰成员函数的两个作用 const在函数前面 总结 const在函数后面 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态 ...
- 第24课.经典问题解析(1.析构函数的顺序;2.const修饰对象;3.成员函数,成员变量是否属于具体对象)
1.当程序中存在多个对象的时候,如何确定这些对象的析构顺序? 单个对象 单个对象创建时构造函数的调用顺序 a.调用父类的构造函数 b.调用成员变量的构造函数(调用顺序与声明顺序相同) c.调用类自身的 ...
- 类中用const限定的成员函数
本文转自http://blog.csdn.net/whyglinux/article/details/602329 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非 ...
- (转)函数后面加const--C++ const成员函数
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于 ...
- C++之const类成员变量,const成员函数
const修饰类的成员函数 const修饰变量一般有两种方式:const T *a,或者 T const *a,这两者都是一样的,主要看const位于*的左边还是右边,这里不再赘述,主要来看一下当co ...
随机推荐
- MySQL删除数据表中重复数据
今天遇到一个问题,数据表的数据有重复的,关键原因在于新增数据时,没有根据条件先判断数据是否存在,当数据存在时进行有关条件的更新,不存在时做新增数据. 对于表中已经存在的数据处理办法的方法: 1.先根据 ...
- Oracle数据类型之nchar
nchar(size) nvarchar2(size) n 代表的意思是编码格式为unicode编码,无论中文或者英文都以一个字符来存放数据. 举例: 比如“a” ,占用一个字符 比如“月”,占用一 ...
- pta 习题集 5-17九宫格输入法
假设有九宫格输入法键盘布局如下: [ 1,.?! ] [ 2ABC ] [ 3DEF ] [ 4GHI ] [ 5JKL ] [ 6MNO ] [ 7PQRS ] [ 8TUV ] [ 9WXYZ ] ...
- 浅谈vuex
很多技术,刚接触的时候:这是啥?用的时候:哟嚯,是挺好用的!加以研究:卧槽,就是这么个逼玩意儿! 最近接手了一个别人写了1/5的vue项目(页面画了1/3,接口啥都没对); 对于表格中的数据项操作以及 ...
- JSON数组成员反序列化
场景: 构想客户端能够传递如下格式JSON字符串到服务端: {"KeyValueSetList":[{"SN":"RQ1001"," ...
- Django之logging日志使用
Logger模块 是python中用于便捷记录日志且线程安全的模块 使用logging模块记录日志涉及四个主要类: logger提供了应用程序可以直接使用的接口: handler将(logger创建的 ...
- PAT 1100 Mars Numbers[难]
1100 Mars Numbers (20 分) People on Mars count their numbers with base 13: Zero on Earth is called &q ...
- 临时表单导出Excel
function ExportExcel(url, vals) { var form = jQuery("<form action='" + url + "' me ...
- devise 自定义手机号登录
user model中配置 validates_uniqueness_of :phone def email_required? false end 修改user migration文件,给phone ...
- hdu5139
这题需要我们计算 这个 因为n<10000000空间过大 那么我们可以计算出 当n可以被10整除的时候我们就将n/10记录下来当我们要查询的时候去暴力计算他们与整十之间的数去暴力去做就好了 这个 ...