Ruminations on C++ 是由Andrew Koenig 与Bjarne Stroustrup写的,贝尔实验室成员,1986年从事C语言研究,还有一本书是《C缺陷与陷阱》。
简单来说,本书就是强调了一个理念。认字最多的人一定是最好的作家吗?不是,讲好故事才是一个好作家的标配。The hard part of programming is not learning the details of language features——it is understanding how to solve problems. 所以编程中最困难的地方不是去学习语言的细节,而是理解问题的解决之道。
书中主要表达了,
C++最基本的设计理念就是"用类来表示概念";
C++解决复杂性的基本原则是抽象;
面向对象思想是C++的手段之一,而不是全部。
所谓面向对象编程,就是使用继承和动态绑定机制编程。也就是两个及以上的类型,至少有一个共同操作,也至少有一个不同操作,否则就不需要继承。其次,必然有一个场景,需要在运行时从这些类型中挑选一个,否则也不需要动态绑定机制。
继承让我们抓住了各种节点类型之间的相似之处,而动态绑定帮助我们为各种类型节点定义操作,让编译器来负责安排在运行时能够调用正确的函数。
C++在运行时性能上做了一个很好的折中,能够在"一切都是对象"的语言与"避免任何抽象"的语言之间取得恰到好处的平衡,这就是C++的实用性。
从语言本身来说,C++是挺"温柔"的,他敏锐、高效、成熟、稳重、分寸感很强、最重要的是"自主"。
挑几个比较有趣的章节讲一下
1.Bjarne Stroustrup 在The C++ programming Language(1991)提到的定义句柄类,简单来说,就是将引用计数从数据中分离出来,把引用计数放入它自己的对象中。
得简单介绍下句柄,它允许在保持代理的多态行为的同时,避免进行不必要的复制。
handle应该"控制"它所绑定到的对象,创建和销毁。从效果上来说,handle就是一种只包含单个对象的容器。
因为使用上通常是复制句柄,我们必须了解有多少个句柄绑定在同一个对象上,只有这样才能确定应当在何时删除对象。而通常使用引用计数(use count)来达到目的。所以设计了定义一个新的类,来容纳一个引用计数和一个Point对象。
但这种技术有一种缺点,为了把句柄捆绑到类T的对象上,必须定义一个具有类型为T的成员的新类,较为繁琐。使用定义句柄类会更加简单。
将引用计数从Point里面分离后,便会改变对句柄类的实现。不再有指向UPint的指针,此时只有指向Point的指针和指向一个int的指针表示引用计数。然后再定义一个新类即可。然后再抽象一下即可。
最后就是将引用计数类当成句柄实现的一部分,与各种不同的数据结构协同工作,简化了引用计算句柄实现,使得handle类与其他传统方式实现的类同样容易使用,且更加灵活。
2.Generic iterators 泛型迭代器
|
|
这里面定义了类P,使用了同一个find函数来对数组、链表、文件或者其他的数据结构进行查找,经典的模板编写,适用于不同的数据结构和参数类型的函数。
理解了这个,就深入一下,探究迭代器类型和算法之间的关系。
首先我们对迭代器进行分类。
1.输入迭代器,满足这些需求的类型允许我们按照某个预定的顺序去读,序列中的元素。这个输入迭代器,既不是某个特殊类型也不是对象。
2.输出迭代器,就是对序列中进行写操作。
这时候,可以用输入和输出迭代器写一个泛型复制函数了.
|
|
上面比较容易理解,不过一般都是写成
|
|
3.前向
4.双向
5.随机
譬如说
|
|
迭代器在性能上是有所保障的,譬如说一个双向迭代器从序列的第n个元素退后到第n-1个元素的时间复杂度是O(n)。但STL赋予迭代器的支持,分摊执行时间必须是O(1)。
所谓泛型算法就是:对于所操作的数据结构的细节信息,只加入最低限度的了解。甚至是不需要。
通过建立一些指针,来分析一下
|
|
|
|
就是被迭代器值start和end限定的序列复制到一个以迭代器dest为开始位置的序列中,对p*的赋值在d后面放入空字符(c的要求)。
加一点理解。
如果我们想要找某个特定值相等的最后一个,而不是通常的第一个。
可以使用双向迭代器。
|
|
还可以再深入一点。
直接自动反向。
创建一个新类型TR,使用"邻接技术"将T转换为TR,并且保障++和–都能使用,以及常规的复制、赋值、比较和解除dereference都能使用。
|
|
然后,我们就可以随便找到第一次出现的位置,和最后一次出现的位置。
|
|
迭代器配接器可以极大减少要写的算法数量,达到事半功倍的效果。
差不多就谈到这儿了。
这是在一个新语言的创造中心里,思考与实践的Koenig写的书,也就是常识成为常识之前(hhh点题了)。Bjarne,Rob Murray,Martin Carrcoll,Barbara Moo与Koenig等这些人一起开创了C++时代,成为一个强大的、稳健的、成熟的高级语言。
这也就是本书的意义所在,要知其然,也更要知其所以然。但它带来的思考不仅仅是这些。历史总与现在遥遥相合,在这个时代里创造新的技术,也要走同样的路的。
用Koenig的话来作为结束吧,
As a result, the ideas in this book hava become more important with time.
时光如筛,必现所金。