呼……这本书总算是看完了,前前后后看这本书大概花了二十来天,总算看完了(更准确的 说是翻完了)这本砖头一样厚(还是块加厚版的砖)的书。
你要是问我记住了些什么,我只能说啥也没记住,C++标准库的内容终究还是太多,细节太 多,能装在脑子里的东西真的很少。其实我在看这本书之前就知道会是这个结果,所以也 没有觉得自己白读了这本书,留在脑海中不是也不应该是具体的细节,而是关于标准库的 一些感悟,前面读这本书的时候陆陆续续也有写一些文章来记录这些东西。
我为什么读这本书
这本书是关于C++标准库的一个权威的指南,其实读这本书的原因和学标准库的原因是一样
的。目前的任何一门语言都是语言的核心+语言的标准库
,没有掌握标准库之前,我们都
不能说自己掌握了这门语言。我希望自己能够掌握这门语言,所以我在了解了基本的语法
之后读了这本书。如果你想掌握这门语言,我也推荐你看这本书。
我曾经在知乎上看到过一个观点:
一门语言要么是语言核心语法难,要么是它的库很难
对于C++来说,是这两者都很难,C++之所以会这么难学原因估计就在于此。
最大的体会
读完这本书,突然发现其实自己对于C++的了解非常的有限。过去的自己对于C++的理解仅
仅停留在C++ OOP
的角度,C++标准库让我体会到C++范型编程
的强大之处。我自己对于
范型只停留在会用(甚至都不太会用)的级别,自己动手进行范型编程的能力基本为零,
而这种能力的缺失可以说让我丧失了C++威力的半壁江山。
在OOP
的世界里,我们一直提倡面向接口编程,而对于C++来说,类型就是接口,所以整
个系统都在和类型打交道,强大的静态类型系统也被认为是C++的一项法宝。当然C++并没
有把接口和实现区分的非常清楚[^1],这也是很多人指责C++的一个原因。
范型编程完全是另外一种思维的存在,范型的关键思维在于像什么就是什么
而不去在乎
它真正到底是什么。所以指针可以当成迭代器用,函数指针和函数对象在范型角度看来并
没有区别,类型在范型编程中并没有太大的作用。这种思维的背后的逻辑才是真正纯粹的
面向接口编程,只要你提供正确的接口,你就可以正确的运行,至于你到底是什么类型对
于我来说根本不重要。从这个角度来说,Python
编程就是范型编程,因为Python
中你
只需要确定一个对象有某个接口,至于对象的类型你可以完全不管。
C++标准库中的核心武器:STL
的设计就是这种逻辑,我渐渐的明白,为什么很多大师级
的人物更倾向于使用namespace
中定义普通函数而不是类的内部定义成员函数。那些嘲笑
C++并自诩完全面向对象的Java程序员是多么的可笑。
这些理解不一定正确,它是我看完STL迭代器和算法之后最大的一种体会,其实范型真的不 仅仅是把容器类型参数化而已。
最容易忽视的东西
对我来说,整个库中最容易被我忽视的东西是STL算法
,其实其中的算法包罗万象,远远
超过我原来了解的范围。也许我们不应该使用:
1 | for (auto beg = v.begin(); beg != v.end(); ++beg) { |
而是考虑:
1 | for_each(v.begin(), v.end(), [] (const value_type& elem) { |
我们经常需要考虑如何在一次 for
循环中删除掉某个元素而保证 iterator
有效,其
实我们应该考虑能否直接用 remove_if
来完成这一功能。
这样的例子很多,我们一直重复的一些动作其实STL
中早就为我们封装好了算法,只不过
在没有发现之前,我们总是在不断的重复着那些我们自以为很优雅的解法。
最容易自以为懂了的东西
其实这本书中的大部分内容以前都不太全面的接触过:智能指针
,STL
,字符串
,
I/O
,正则表达式
,线程
等等。我自以为自己懂了却发现完全不懂的东西是I/O
这
一部分。
1 | cout << "hello world" << endl; |
这样的语句大家都会用,但是我从来没有去考虑过所谓的 endl
到底是什么东西。后来
我知道 endl
是一种操控器,自以为自己懂了,却从来没有想过
1 | cout << endl; |
为什么可以换行,并把内容显示在屏幕上。看完这本书之后我才知道其实 endl
是一个
函数,它接收一个 stream
作为它的参数。伪代码去下:
1 | ostream& endl(ostream& os) { |
而 ostream
的 <<
操作符有一个重载版本,接收一个函数指针作为它的参数:
1 | ostream& ostream::operator << (ostream& (*op) (ostream&)) { |
就是是为什么 cout << endl;
可以正常工作的原因。你完全可以扩展自己的“操控器”来
完成自己额外的需求。
I/O
其实是一个设计非常好的库,它的各大组件之间的职责分派非常明确,stream
其实自身根本不处理实际的输入输出,这些东西都委托给了 streambuf
处理。I/O
本
身可能在项目中使用的并不是特别的多,但是个人觉得它的源码库有机会还是很值得读一
读的。
黑魔法
C++11有许多新的特性,比如:变参模板,右值引用等等。这些特性造就了一堆的黑魔法出
现,比如tuple
,binder
,function
。很遗憾这本书并没有深入的讲解这些黑魔法的
具体实现机制,只是提到了它们的用法。关于 tuple
的实现,《深入理解C++11:C++11
新特性解析与应用》这本书中有比较详细的介绍。关于 binder
看过一篇相关的文章
图解boost::bind,感觉还不错。