【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 ...
随机推荐
- 标准C++中的string类的用法总结(转)
http://www.cnblogs.com/xFreedom/archive/2011/05/16/2048037.html 相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的 ...
- public void Delete(List EntityList) where T : class, new()类型参数约束
查找后发现这是类型参数约束,.NET支持的类型参数约束有以下五种: where T : struct | T必须是一个结构类型 where T : class T必须是一个类(class)类型 whe ...
- JavaSE replaceAll 方法
private String srcStr = "index\\.php\\?action=";//要替换的原字符串 private String destStr = " ...
- php smarty 配置四个存放目录
require("Smarty.class.php"); $smarty = new Smarty(); $smarty -> template_dir = "./ ...
- Android:WebView深入使用
webView = (WebView) findViewById(R.id.info_detail_webview); WebSettings webSettings = webView.getSet ...
- INV Close Period & GL Import Journal > DML tables
1. (N) Inventory > Accounting Close Cycle > Inventory Accounting Periods Insert data ...
- HTML颜色编码
Web安全色 #000000 #000033 #000066 #000099 #0000CC #0000FF #003300 #003333 #003366 #003399 #0033CC #0033 ...
- android 欢迎界面的淡入效果
package com.example.spinnertest; import android.app.Activity; import android.content.Intent; import ...
- 安卓使用WIFI调试程序
不知怎么回事,USB老是掉,真心烦.于是想着用WIFI可不可以调试呢,去百度一搜,果然可以.下面我说一下我的方案. 1.使用APWIFI创建WIFI热点,用安卓手机连接该热点,试试手机可以上网不. 2 ...
- C#中使用自定义的纸张大小
using System.Drawing.Printing; using System.Drawing; private void Test() { PrintDocument m_pdoc = ne ...