More Effective C++ - 章节一 : 基础议题
1. 仔细区分 pointers 和 references
references和pointers的差别描述如下:
pointer:当需要考虑"不指向任何对象"时,或者是考虑"在不同时间指向不同对象"的能力时,应该采用pointer。前一种情况可以将pointer设为null,后一种可以改变pointer所指对象。
reference:当确定"总是会代表某个对象",而且"一旦代表了该对象就不能再改变",那应该使用reference。 reference不能为空,因此无需做判空操作,相对pointer使用效率更高。某些操作符重载 operator[],operator= 采用reference实现。
结论: 当知道需要指向某个东西,而且绝不会改变指向其他东西,或是当实现一个操作符而其语法需求无法由pointers实现,就应选择references。 其任何时候,请采用 pointers。
2. 最好使用 C++ 转型操作符
由于旧式的c转型几乎允许任何类型转换为任何其他类型,这样是十分拙劣的,如果每次转型能够精确地指明转型意图,会更好。还有就是旧式转型难以辨识,导致查看代码时,会遗漏转型操作。C++ 引进4个新的转型操作符:
旧式 C 转型:
(type) expression
C++ 转型:
```
1. static_cast(expression) :
基本拥有与 C 旧式转型相同的威力和意义
- dynamic_cast(expression) : 
 用来执行继承体系中"安全的向下转型或者跨系转型动作",我们可以利用dynamic_cast,将 "指向父类对象的指针或引用" 转型为 "指向子类对象的指针或者引用"
 ,并得知是否转型成功,转型失败会返回一个null指针(当转型对象时指针)或一个exception(当转型对象时reference)
- const_cast(expression) : 
 改变表达式常量性(constness)或者 变易性(volatileness)
- reinterpret_cast(expression) : 
 与编译平台相关,不具有移植性。最常用用途是转换 "函数指针" 类型,不到非用不可的地步不用,因为某些情况下会出现转型不正确。
例如:
typedef void (*FuncPtr)();
FuncPtr funcPtrArrary[10];
int doSomething();
funcPtrArrary[0] = reinterpret_cast (&doSomething); // 将返回值为 int 的函数指针转换为返回值为void*
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">如果你想为一个不涉及继承机制的类型执行转型动作,可使用static_cast;要改变常量性,必须使用const_cast;涉及继承机制,使用dynamic_cast 或者 static_cast; reinterpret_cast 把一个指针转换成一个整数,也可以把一个整数转换成一个指针。</p>
<p style="color: #AD5D0F;font-weight: bold;font-size: 20px; font-family: '微软雅黑';">3. 绝对不要以多态的方式处理数组 </p>
------
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">大致代码如下:</p>
// 简单继承关系
class BST{...};
class BalancedBST: public BST{...};
// 打印接口
void printfBSTArray(ostream& s, const BST arrry[], int numElements)
{
for(int i = 0; i < numElements; ++i){
s << array[i];
}
}
BalancedBST bBSTArray[10];
...
printfBSTArray(cout, bBSTArray, 10); // 发生不可预期问题
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">上述代码中,<font color="#ff0000">编译器为了能够访问整个数组,编译器必须有能力决定数组对象大小,编译器认为大小为BST类大小,但是我们传入的是其子类,而子类对象大小肯定是大于父类的,因此导致这里会发生不可预期错误</font>。 </p>
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微软雅黑';">多态和指针算术不能混用。而数组对象几乎总是会涉及指针的算术运算,所以数组和多态不要混用。</p>
<p style="color: #AD5D0F;font-weight: bold;font-size: 20px; font-family: '微软雅黑';">4. 非必要不提供 default constructor </p>
------ 
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">由不带参数的构造函数,或者为所有的形参提供默认实参的构造函数,被称为默认构造函数(default constructor)。</p>
class foo
{
public:
foo(); // 默认构造函数
...
};
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">在一个完美世界中,凡可以"合理的从无到有生成对象"的class,都应该内含默认构造函数,而"必须有某些外来信息才能生成对象"的class,则不必拥有默认构造函数。<font color="#ff0000">但是,当一个类缺乏default constructor,使用时会受到限制。</font></p>
class foo
{
public:
foo(int Id); // 构造函数
...
};
foo bestfoo[10]; // 错误! 无法调用构造函数
foo *best = new foo[10]; // 错误! 无法调用默认构造函数
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">有介绍三种办法来解决无默认构造函数的限制:</p>
<p style="font-size: 15px; letter-spacing:1px; font-family: '微软雅黑';">1. non-heap 数组</p>
foo fooTest[] = {foo(1), foo(2), foo(3)}; // 构造函数获得id,可以成功
<p style="font-size: 15px; letter-spacing:1px; font-family: '微软雅黑';">2. 指针数组。 缺点:指针数组要删除,否则内存泄漏;保存指针,浪费内存。</p>
typedef foo* foo_ptr;
foo_ptr bestfoo[10]; // 没问题,存在的指针,不用调用构造函数
foo_ptr *best = new foo_ptr[10] // 也没问题,数组堆上存的是指针
for(int i = 0; i < 10; ++i){
best[i] = new foo(Id number); // 传入ID 初始化对象
}
<p style="font-size: 15px; letter-spacing:1px; font-family: '微软雅黑';">3. placement new。分配内存时可指定内存位置。</p>
// 首先申请一块适当大小的缓存,可以是堆上的,也可以是其他特殊缓存(例如共享内存)
void *rawMemory = operator new;
// 让 best 指针指向该块内存首地址
foo* best = static_cast<foo*>(rawMemory);
// 然后利用 placement new 构造内存中的 foo 对象
for(int i = 0; i < 10; ++i){
new (&best[i]) foo(Id number); // (&best[i]) : 内存位置
}
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微软雅黑';"><font color="#ff0000">缺乏 default constructor 类的第二个缺点,将不适用于许多基于模板实现的容器类</font>。</p>
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-weight: bold; font-family: '微软雅黑';"><font color="#ff0000">第三个缺点,虚基类没有默认构造函数,将导致所有继承类都要注意提供虚基类构造函数自变量,十分麻烦</font>。</p>
<p style="font-size: 15px; text-indent:2em; letter-spacing:1px; font-family: '微软雅黑';">缺乏默认构造虽然会导致上述三种限制,但是如果不需要默认构造函数的类却加了默认构造函数,将导致该类内部member functions逻辑变得复杂,以及影响调用该类的客户代码的效率。 因此非必要不提供 default constructor。</p>
<p style="font-size: 15px;text-indent:60em;letter-spacing:1px; font-family: '微软雅黑';">2018年10月1日14:59:02</p>More Effective C++ - 章节一 : 基础议题的更多相关文章
- More Effective C++ 基础议题(条款1-4)总结
		More Effective C++ 基础议题(条款1-4)总结 条款1:仔细区别pointers和references 如果有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表 ... 
- ###《More Effective C++》- 基础议题
		More Effective C++ #@author: gr #@date: 2015-05-11 #@email: forgerui@gmail.com 一.仔细区别pointers和refere ... 
- More Effective C++: 01基础议题
		01:仔细区别 pointers 和 references 1:没有所谓的null reference,但是可以将 pointer 设为null.由于 reference 一定得代表某个对象,C++ ... 
- 《Getting Started with Storm》章节一 基础
		注:括号里的字,并且是(灰色)的,是我个人的理解,如有差错,欢迎交流 Storm是一个分布式的.可靠的.容错的数据流处理系统(流式计算框架,可以和mapreduce的离线计算框架对比理解).整个任务被 ... 
- MoreEffectiveC++Item35(基础议题)(条款1-4)
		条款1:区别指针和引用 条款2:最好使用C++转换操作符 条款3: 绝对不要以多态的方式处理数组 条款4: 避免无用的缺省构造函数 条款1:区别指针和引用 1.指针(pointer) 使用[*/-&g ... 
- More Effective C++ - 章节二 : 操作符(operators)
		5. 对定制的 "类型转换函数" 保持警觉 允许编译器执行隐式类型转换,害处多过好处,不要提供转换函数,除非你确定需要. class foo { foo(int a = 0, in ... 
- 章节1-Prometheus基础(1)
		目录 一.Prometheus安装部署 1. 简介 监控的目的 Prometheus的优势 2. Prometheus工作流程: 2.1 服务端 2.2 客户端 2.3 metrics主要数据类型 3 ... 
- C++学习书籍推荐《More Effective C++》下载
		百度云及其他网盘下载地址:点我 编辑推荐 <More Effective C++:35个改善编程与设计的有效方法(中文版)>:传世经典书丛 媒体推荐 <Effective c++&g ... 
- C#基础--之数据类型
		C#基础--之数据类型 摘自:http://www.cnblogs.com/tonney/archive/2011/03/18/1987577.html 在第一章我们了解了C#的输入.输出语句后,我这 ... 
随机推荐
- mysqldump 工具使用详解——参数选项
			mysqldump 简介 mysqldump 是一种用于逻辑备份的客户端工具,它会产生一套能够重新构建数据库或表的SQL语句.所谓逻辑备份:是利用SQL语言从数据库中抽取数据并存于二进制文件的过程.逻 ... 
- LuoguP2115 [USACO14MAR]破坏Sabotage【二分答案】By cellur925
			本来是想找一道生成树的题做的...结果被洛咕的标签骗到了这题...结果是二分答案与生成树一点mao关系都没有.... 题目大意:给你一个序列,请你删去某一个$l~r$区间的值($2<=i< ... 
- 树链剖分学习笔记 By cellur925
			先%一发机房各路祖传树剖大师%%%. 近来总有人向我安利树剖求LCA,然鹅我还是最爱树上倍增.然鹅又发现近年一些题目(如天天爱跑步.运输计划等在树上进行操作的题目),我有把树转化为一条链求解的思路,但 ... 
- wamp2.5版本配置多端口虚拟主机
			1.保证httpd.conf下 LoadModule php5_module "D:/E/php/wamp/bin/php/php5.5.12/php5apache2_4.dll" ... 
- two_sum问题
			def two_sum(li, target): for i in range(len(li)): for j in range(i+1, len(li)): if li[i] + li[j] == ... 
- 后缀数组  DC3构造法 —— 详解
			学习了后缀数组,顺便把DC3算法也看了一下,传说中可以O(n)复杂度求出文本串的height,先比较一下倍增算法和DC3算法好辣. DC3 倍增法 时间复杂度 O(n)(但是常数很大) O(nlo ... 
- [洛谷P3512 [POI2010]PIL-Pilots]
			题目链接: 传送门走这里 题目分析: 感觉不是很难啊--不像是蓝题(AC量也不像)恶意评分? 少打了一个+1调了半天,就这样居然还能过60pts?我思路和题解第一篇高度重合是什么鬼啊,太过分了吧本来还 ... 
- April Fools Contest 2017 C
			Description DO YOU EXPECT ME TO FIND THIS OUT? WHAT BASE AND/XOR LANGUAGE INCLUDES string? DON'T BYT ... 
- Math Show CodeForces - 846B
			题目 题意: 有n个任务,每个任务有k个子任务,有m的时间来完成任务.每个任务的第i个子任务需要时间都是ti.完成一个子任务获得一分,完成一个大任务的所有子任务额外得一分.问如何在时间不超过m的情况下 ... 
- Cake slicing UVA - 1629
			UVA - 1629 ans[t][b][l][r]表示t到b行,l到r列那一块蛋糕切好的最小值d[t][b][l][r]表示t到b行,l到r列区域的樱桃数,需要预处理 #include<cst ... 
