【03】尽可能使用const
1、为什么搞出const关键字?
const指定一个语义约束,指定一个对象不可修改。如果一个对象不可修改,就应该说出来。
2、const与指针
const可以修饰指向之物,也可以修改指针本身。STL中的迭代器是对指针的封装,因此,迭代器也有两个概念:指向常量对象的迭代器和常量迭代器。
vector<int>::const_iterator; //指向常量的迭代器
const vector<int>::iterator; // 常量迭代器
3、const可以与方法产生关联,可以用在方法前,方法中(形参表中),方法后。首先考虑,用在方法前,表示返回值是常量。为什么要返回const对象呢?
我们知道,方法返回值是一个临时对象,只有类型,没有名称,这个临时对象是方法内局部对象的副本。如果返回不是一个常量,客户端就能实现下面的暴行:
Rational a,b,c;
(a*b)=c; //对方法返回值进行赋值。
对于内置类型,这样的赋值行为是错误的。对于自定义类型,也应该报错。有一个准则要遵守:自定义类型应该和内置类型在行为上保持一致,除非有特殊情况。因此,为了避免客户端对方法返回值进行赋值,请返回一个const对象。
4、const在方法中,也就是出现在形参表中,这种情况很好理解,表示形参不可修改。需要注意的是:形参表不同,可以构成过载。如果形参表相同,只是常量性不同,能否构成过载?能不能构成过载的关键是:编译器能不能根据实参确定调用哪个方法,也就是过载方法的匹配程度不一样。
如果形参是引用或者指针,可以构成过载,这种情况下,形参是实参的别名,根据实参的常量性,可以确定调用哪个方法。
如果形参不是引用或者指针,不能构成过载,这种情况下,形参是实参的副本,与实参没有了关系,他们和实参的匹配程度是一样的。
5、const在方法后,表示常量方法,应该尽量使用常量方法。有两个好处:a、接口容易理解,明确表示不会修改对象内容;b、使得const对象可以调用。
考虑,我们知道non-const对象可以调用const成员方法,但是,const对象不能调用non-const成员方法,因为non-const成员方法可能会修改对象。为了让const对象调用non-const成员方法,有两种办法:一是使用const_cast<T&>或者const_cast<T*>去除对象的常量性,二是如果不修改对象,使用const成员方法,显然第二种办法更好。
6、根据成员方法的常量性,可以过载。为什么?我们知道成员方法有个隐式的常量this指针(不能指向其他对象),const成员方法限制了this指针指向const。因此,编译器可以根据方法拥有者的常量性,决定哪个方法更匹配。
7、如果返回对象的内部数据,const成员方法应该返回const引用,防止外部修改,non-const成员方法应该返回non-const引用。这里特别注意一点,内置类型的临时对象是不可修改的(exception的临时对象是可以修改的),也就是说,内置类型的临时对象不能赋值给non-const引用,考虑一下为什么?
方法返回对象的内部数据,返回值不是引用,而是内部数据的副本。第一个理由上面讲了,防止客户端对返回值赋值,第二个理由是,如果返回值不是const,就可以赋值给non-const引用,程序员用这个引用期望修改对象内部数据,是办不到的,这个时候修改的是临时对象,这往往不是程序员所期望的。
8、返回对象的内部数据,const成员方法为什么返回const引用?
我们知道,const成员方法的语义是说,不修改对象。但是由于暴露了内部数据,自己承诺不修改,但是由于自己的原因,暴露了内部数据,导致外部可以间接修改对象(我不杀伯仁,奈何伯仁因我而死)。为了避免这种情况,返回const引用,限制外部也不能修改。
9、在有些极端情况下,const成员方法也要修改对象的一部分内部数据,但是我又不想把它设计成non-const成员方法,因为non-const成员方法可以修改对象内的任意数据。这种情况下,可以使用mutable修饰字段,明确表示这些字段可以在const成员方法中修改。
10、对于过载的const成员方法和non-const成员方法,做的事情一样,只不过一个返回const引用,一个返回non-const引用,如何避免代码重复呢?
就是让一个方法调用另一个方法,让non-const成员方法调用const成员方法,这里要做两个强制转化,首先使用static_static<const T *>,把常量this指针转化为指向常量对象的常量this指针,然后使用const_cast<T&>,去除返回值的常量性。
注意:不能反向调用,也就是说,不能使用const成员方法调用non-const成员方法,因为后者可能修改对象内容。
【03】尽可能使用const的更多相关文章
- Effective C++ -----条款03:尽可能使用const
如果关键字const出现在星号左边,表示被指物是常量:如果出现在星号右边,表示指针自身是常量:如果出现在星号两边,表示被指物和指针两者都是常量. char greeting[] = " he ...
- 《Effective C++》读书笔记 条款03 尽可能使用const 使代码更加健壮
如果你对const足够了解,只需记住以下结论即可: 将某些东西声明为const可帮助编译器侦测出错误用法,const可被施加于任何作用于内的对象.函数参数.函数返回类型.成员函数本体. 编译器强制实施 ...
- 条款03 尽可能使用const
一.概述 使用const约束对象:可以获得编译器的帮助(指出相关出错的地方) const与成员函数:const重载.转型.避免代码重复 二.细节 1. 为什么有些函数要返回const对象(看上去没必要 ...
- Effective C++ 之 Item 3:尽可能使用 const
Effective C++ Chapter 1. 让自己习惯C++(Accustoming Yourself to C++) Item 3. 尽可能使用 const (Use const whenev ...
- Effective C++ 条款03:尽可能使用const
场景一 用于修饰指针 char greeting[] = "Hello"; char* p = greeting; // non-const pointer, non-const ...
- 条款03:尽可能使用const
目录 1. 总结 2. const对象 3. const函数返回值和函数参数 4. const成员函数 const成员函数的重要性 bitwise constness logical constnes ...
- C++ const用法 尽可能使用const [转载]
C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的.如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助. 1.c ...
- 尽可能使用 const
前言 const 关键字是常量修辞符,如果要告知编译器某个变量在程序中不会发生改变,则可将其声明为 const. 但,对 const 关键字的认识不能仅仅停留在这一层 - 它提供了很多更强大的功能. ...
- C++ const用法 尽可能使用const
C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的.如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助. 1.c ...
随机推荐
- 1319-n皇后问题
描述 在n×n 格的棋盘上放置彼此不受攻击的n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n后问题等价于在n×n格的棋盘上放置n个皇后,任何2 个皇后不放在同一 ...
- POJ 3308 Paratroopers(最小割EK)
题目链接 题意 : 有一个n*m的矩阵,L个伞兵可能落在某些点上,这些点的坐标已知,需要在某些位置安上一些枪,然后每个枪可以将一行或者一列的伞兵击毙.把这种枪安装到不同行的行首.或者不同列的列首,费用 ...
- 练习PYTHON之GEVENT
这个只是作了第一个样例,里面还有很多高级的技巧,希望以后用得着. 我觉得因为以前看过几本LINUX内核,关于异步非阻塞IO,信号,锁之类的,所以理解起来,还可以. import gevent def ...
- Jmeter java协议配置文件导入
一. 方法一 通过ClassLoader获取当前路径,想在java脚本里读取druid.properties,路径如下 apache-jmeter --bin --druid.properties 相 ...
- java区分大小写,使用TAB进行缩进,public类名只能有一个,而且文件名与类名保持一致.
java的类必须大写 java区分大小写,使用TAB进行缩进,public类名只能有一个,而且文件名与类名保持一致. 在dos用上下箭头,调用已用过的命令
- SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-003-Spring对AOP支持情况的介绍
一. 不同的Aop框架在支持aspect何时.如何织入到目标中是不一样的.如AspectJ和Jboss支持在构造函数和field被修改时织入,但spring不支持,spring只支持一般method的 ...
- 《ArcGIS Engine+C#实例开发教程》第六讲 右键菜单添加与实现
原文:<ArcGIS Engine+C#实例开发教程>第六讲 右键菜单添加与实现 摘要:在这一讲中,大家将实现TOCControl控件和主地图控件的右键菜单.在AE开发中,右键菜单有两种实 ...
- RxJava开发精要5 – Observables变换
原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...
- TCP 协议如何保证可靠传输
一.综述 1.确认和重传:接收方收到报文就会确认,发送方发送一段时间后没有收到确认就重传. 2.数据校验 3.数据合理分片和排序: UDP:IP数据报大于1500字节,大于MTU.这个时候发送方IP层 ...
- C++构造函数,复制构造函数和析构函数专题
链接:http://wenku.baidu.com/view/d9316c0e52ea551810a6872a.html 本文作者:黄邦勇帅本文是学习 C++中的最基本的内容,因此学习 C++就应全部 ...