有机会应该去了解下STL背后的数学思想
此书在amazon.com上几乎得到了全五星的评论。800页的大部头,我大概花了一周不到的时间基本读完,并动手敲完了前10章的绝大部分demo代码。
STL的设计思想(通过迭代器将数据结构和算法分离,获得通用性的程序组件)是此书的精华。其余的部分诸如复数complex,valarray,bitset,strings,国际化等等,了解一下即可,没有必要深究。还有令人纠结的auto_ptr,本身就是一个设计失败的产物,当一个组件给你提供了3条功能却告诉你为了使用这3条功能你需要遵守10大戒律的时候,这个组件本身的设计没准就是有问题的。很不幸,在我看来,auto_ptr就是这样的组件,使用它会带上很大的心智负担(C++的很多特性都是如此,看上去很强大很花哨,但深究起来发展这里面的陷阱很多,会给使用者带来很大的心智负担)。
此书中还有很多句子在前后反复强调,一再呼应,比如中译本的P444和P453,都有这样“最后新增加的一个pop()调用动作……程序输出如下:”这样的句子。再比如统一类型的很多算法,其使用要点和能力限制都是差不多的,书中也反复的强调。这当然可以拿德国人的严谨性说事,但也显得书籍比较罗嗦。这部分也占了很大的篇幅。
去除以上两部分,此书最有价值的东西就在300页左右,也就是第5-10章的内容,细说起来,就是STL,容器、算法、迭代器、仿函数。
STL的核心设计思想是数据结构和算法的分离,这个从某种意义上来讲,是和OOP的思想背道而驰的。所以在STL中只用到了Object-based的东西,却没有用到Object-oriented,STL没有用到继承。STL之父Alexander Stepanov也并不是100%赞同OOP的。Alexander本身是俄罗斯某大学数学系出身,因此STL背后有着很深刻的数学思想,为此Alexander专门写了一本书,"The Elements ofProgramming"。
我的数学基础并不能参透STL这些背后的数学思想,不过仅有的一些lisp和scheme的知识,倒让我在STL中的某些组件里面,找到了一些似曾相识的东西。
比如像functor(仿函数),我觉得仿函数的本质在于将函数的地位提升到和C++ class同样的一等公民的位置。在scheme中,函数(操作)和数据一样,都可以作为一等公民,可以当做参数传递、返回。而在C++中,数据才是一等公民,C++ class的各种机制(构造函数、析构函数、运算符重载等),无非也就是让用户自定义的class拥有和built-in的类型一样的使用接口和特性(比如像std::complex和int)。但函数本身在C++中并不能通过很轻易的方式成为一等公民。要想像普通数据一样传递函数,需要用到函数指针。而functor的存在,就是为了通过重载operator(),来实现传递“函数(操作)”的目的。至于优点和好处,此书上已经说的很清楚了。
再比如像transform()、for_each()、accumulate()算法,如果你读过SICP前两章,你就会发现这其实和lisp/scheme里面的map/reduce函数有异曲同工之妙。MapReduce?没错,就是那个MapReduce,google的那个MapReduce。
语言是会影响人的思维的。所以我并不赞同“语言和工具不重要”的这种论调,没错,语言是相通的,C++可以做到的事情,汇编一样可以,本质上大家都是Turing-Complete的。但是Turing-Complete并不意味着相同的表现形式和使用难度,多学几种语言,多了解几种思想,不盲目崇拜,跳出语言的框架去学习语言,是很重要的。
扯远了,回头说说阅读此书的基础和后续吧。首先需要对C++有比较好的了解,如果连const、reference都搞不清楚,还是不要读此书了。其次最好对模板技术有一些了解,最好能看些"C++ Template: The Complete Guide",了解下type traits这类技术。
读完此书后,找个机会动手实现下STL的各种container和一些基础算法,Mark A.Weiss有一本老书"Data Structures and Problem Solving Using C++",包含了很多STL的实现代码和STL的应用,很不错,可惜现在很难搞到。有机会再去读读侯先生的"STL源码剖析"。当然,更高阶的,什么c++ template metaprogramming,我就不继续了。
顺便,侯先生在此书中不遗余力的推荐它的译作和著作,我总算是没抵住诱惑,买了本"STL源码剖析",正在消化中。
STL的设计思想(通过迭代器将数据结构和算法分离,获得通用性的程序组件)是此书的精华。其余的部分诸如复数complex,valarray,bitset,strings,国际化等等,了解一下即可,没有必要深究。还有令人纠结的auto_ptr,本身就是一个设计失败的产物,当一个组件给你提供了3条功能却告诉你为了使用这3条功能你需要遵守10大戒律的时候,这个组件本身的设计没准就是有问题的。很不幸,在我看来,auto_ptr就是这样的组件,使用它会带上很大的心智负担(C++的很多特性都是如此,看上去很强大很花哨,但深究起来发展这里面的陷阱很多,会给使用者带来很大的心智负担)。
此书中还有很多句子在前后反复强调,一再呼应,比如中译本的P444和P453,都有这样“最后新增加的一个pop()调用动作……程序输出如下:”这样的句子。再比如统一类型的很多算法,其使用要点和能力限制都是差不多的,书中也反复的强调。这当然可以拿德国人的严谨性说事,但也显得书籍比较罗嗦。这部分也占了很大的篇幅。
去除以上两部分,此书最有价值的东西就在300页左右,也就是第5-10章的内容,细说起来,就是STL,容器、算法、迭代器、仿函数。
STL的核心设计思想是数据结构和算法的分离,这个从某种意义上来讲,是和OOP的思想背道而驰的。所以在STL中只用到了Object-based的东西,却没有用到Object-oriented,STL没有用到继承。STL之父Alexander Stepanov也并不是100%赞同OOP的。Alexander本身是俄罗斯某大学数学系出身,因此STL背后有着很深刻的数学思想,为此Alexander专门写了一本书,"The Elements ofProgramming"。
我的数学基础并不能参透STL这些背后的数学思想,不过仅有的一些lisp和scheme的知识,倒让我在STL中的某些组件里面,找到了一些似曾相识的东西。
比如像functor(仿函数),我觉得仿函数的本质在于将函数的地位提升到和C++ class同样的一等公民的位置。在scheme中,函数(操作)和数据一样,都可以作为一等公民,可以当做参数传递、返回。而在C++中,数据才是一等公民,C++ class的各种机制(构造函数、析构函数、运算符重载等),无非也就是让用户自定义的class拥有和built-in的类型一样的使用接口和特性(比如像std::complex和int)。但函数本身在C++中并不能通过很轻易的方式成为一等公民。要想像普通数据一样传递函数,需要用到函数指针。而functor的存在,就是为了通过重载operator(),来实现传递“函数(操作)”的目的。至于优点和好处,此书上已经说的很清楚了。
再比如像transform()、for_each()、accumulate()算法,如果你读过SICP前两章,你就会发现这其实和lisp/scheme里面的map/reduce函数有异曲同工之妙。MapReduce?没错,就是那个MapReduce,google的那个MapReduce。
语言是会影响人的思维的。所以我并不赞同“语言和工具不重要”的这种论调,没错,语言是相通的,C++可以做到的事情,汇编一样可以,本质上大家都是Turing-Complete的。但是Turing-Complete并不意味着相同的表现形式和使用难度,多学几种语言,多了解几种思想,不盲目崇拜,跳出语言的框架去学习语言,是很重要的。
扯远了,回头说说阅读此书的基础和后续吧。首先需要对C++有比较好的了解,如果连const、reference都搞不清楚,还是不要读此书了。其次最好对模板技术有一些了解,最好能看些"C++ Template: The Complete Guide",了解下type traits这类技术。
读完此书后,找个机会动手实现下STL的各种container和一些基础算法,Mark A.Weiss有一本老书"Data Structures and Problem Solving Using C++",包含了很多STL的实现代码和STL的应用,很不错,可惜现在很难搞到。有机会再去读读侯先生的"STL源码剖析"。当然,更高阶的,什么c++ template metaprogramming,我就不继续了。
顺便,侯先生在此书中不遗余力的推荐它的译作和著作,我总算是没抵住诱惑,买了本"STL源码剖析",正在消化中。
有关键情节透露