最近一段时间 c++ 社区里最火热的话题莫过于 cppcon2015 了, isocpp 上一堆相关的新闻,其中有一个页面罗列了该会议的全部主题, 匆匆一瞥几乎眼花缭乱,为期一个星期的会议竟有上百个演讲,无论是数量还是内容所覆盖的范围,比之去年都更加丰富,作为一个野生的 c++ 的爱好者,我表示这样的盛会是不容错过的,多么希望能有机会前往现场感受一番,门票倒不是太贵,可惜远隔重洋,只能洒泪遥望。现在 cppcon 已过去一个多星期了,演讲的视频和材料还没全部公开,isocpp 上说要一个月的时间才能搞好,只能耐心等,目前放出来的只有少数几个演讲,比如,由 Bjarne Stroustrup 和 Herb Sutter 主讲的:Writing Good C++14,于是趁着假期虔诚地拜读一番,给信仰充充值。
突然想起来,去年的 cppcon 也放出了很多演讲视频,我只略看了其中一小部分,当时 c++11 用的还比较少,很多东西都没接触,因此有些视频没细看,有的没看懂,现在一年多过去了,很多东西有了很多新的体会,觉得倒是时候回顾一下去年这些人都讲了些什么东西,于是翻啊翻,重看了一些关于网络,并发,类型,模板等相关的演讲,收获很多,这些演讲的主题大部分并不是教别人怎么写代码或介绍新特性之类的,很多是工程实践中的经验总结,以及 show off 一下自家的编程思想,工具等好东西诸如此类。越来越觉得多关注一下业界的动态,了解一下别人在做什么、怎么做的,对开阔一个人的思路和眼界实在有莫大的帮助。
只是很多时候很多东西看过就丢开了,再找时东翻西翻,缺少整理就觉得混乱,所以这篇笔记就随手整理归类一下近一年多看了些什么 c++ 相关的东西,记录记录,也方便需要时去查找回顾,仅此而已。
该主题的内容比较难理解也难以使用,特别是当你想写 lock free code 时。最好的教程我觉得来自于委员会里这方面权威人士的手笔,比如: Herb Sutter, Hans Boehm, 推荐两个视频,都在 msdn chanel9 上:
看完前面两个视频,估计就能对 c++11 里的 threading 和 atomic 相关的库有大概的了解,不过与此同时估计读者脑海里也多了一堆对技术细节的疑问,尤其是 ordering 相关的,此时可以再去看看以下两个长篇,其中一篇是讲硬件实现上的细节,a primer on memory consistency and cache coherence,另一篇则介绍了 linux 内核中 memory barrier 的相关知识与背景
如果你实在很好学,追求极致细节想成为 language lawyer 什么的,这里几个链接,分别是 Hans 和 Herb 当初给 c++ 委员会作的原始提案,细看一下就能知道现在 c++11/14 里相关内容的是怎么来的:
上面的链接都来自权威人士,其中文章大多非常严谨因而可能不够通俗易懂,国外有一位叫 Jeff Preshing 的游戏开发者写了一系列与 memory ordering 相关的博文,他的文章写的很详细,每个概念都有长篇的介绍及相关的代码,如果你看完 Herb 和 Hans 的那些文章后还是有疑问,那么可以尝试再结合一下 Jeff Preshing 的文章来加深一下理解,特别是其中关于 acquire-release, happen-before 及 synchronize-with 这几篇。
最后有一本书介绍给读者,C++ Concurrency in Action,学以致用,作者也是这方面的先行者 Anthony Williams,他的文章博客在网上也传播的很利害,比如 Peterson's algo,Deker's algo 在 c++11 中的实现等。
虽然 BS 谆谆教导不要成为 language lawyer,不要抠太多语言细节,但是。。。不彻底搞懂右值引用又怎么能够理解 move 语义,又怎么能用好新的 STL 呢,更不用说自己写相关的代码了,毕竟语言里本身有许多 arcane 的细节,弄懂了其实还是有助于少踩坑的,再说了,不能写 library 的程序员也算不得好码农。
右值引用是一定要搞懂的,推荐两篇介绍性的长文,其中一篇是 Scott Meyers 写的 Universal References in C++11, 另一篇则由 Thomas Becker 所写 C++ Rvalue References Explained,仔细读完这两篇文章,应该就能彻底搞懂 move, forward 及其背后那些稀奇古怪的东西。
因为右值引用的出现,c++11 里对传参有了一种新的写法(idiom),叫作 sink parameter,简单来说就是必要情况下尽可能多地传值而非传引用,具体可以看看这篇介绍, 由此也引发了许多对 value semantic 的讨论,cpp-next 上有一篇文章值得一读,want speed? pass by value(链接如果没法打开,可以试试这个备份的镜像), Sean Parent 有一个 talk: c++ seasoning 也讲到了这方面的用法,cppcon2014 里有也有一个专门的演讲是谈 value type 的,个人觉得比较有意思。
在学习右值引用的时候,如果你在意细节,相信会遇到一些关于类型推导的疑问(比如 perfect forwarding 里的模板参数类型推导)。关于类型的推导,比如 auto, decltype 的使用,这里也有两篇文档值得一读,很巧分别还是 Scott Meyers 和 Thomas Becker 所写,其中一篇是 Scott 在 cppcon2014 上作的演讲,Type deduction and why you care, 另一篇则是 Thomas 写的 C++ auto and decltype Explained,题外话,auto 和 decltype 是 c++11 里我最喜欢的两个新特性了,auto 自不必说,随手 auto 一下强健的右手少敲多少键盘,decltype 也是实打实的 productivity booster,以前要写各种 traits, result of 来人肉推导返回类型的痛苦岁月从此就一去不复返了。至于模板参数的类型推导,个人觉得也是值得仔细研究总结一下的,以后再补充.(TODO)
语言级别的并发编程也许是 c++11 众多的新特性中引入新概念最多的一块了吧,习惯了从前远古时代简单粗暴的多线程编程模式,到现在满眼 future, promise, async,恍惚会有错觉仿佛已经不是在写 c++,感觉已经变了,味道也变了。确实是变了,变得更加简单,也变得更加容易,所以最好尽早去尝试和适应,熟悉了基本的语法和使用规则之后,强烈推荐 Sean Parent 的这个演讲,better code: concurrency, 这里面 Sean Parent 讲了一些并发编程的基本的准则,best practise 之类的,并且自己重造了一遍 future, promise, packaged_task 等轮子,从而实现了一个简单版的 async continuation (主要是 then()),Sean 的演讲和他的程序一样一惯地简练实际,我个人非常地喜欢,也推荐读者去看看他的 better code 这一系列的演讲,干货很多。
说到 concurrency,Herb Sutter 也写了一系列 effective concurrency 的文章,当然一惯地 Herb 的风格了,以说教的形式指出 best practice,如果嫌文章太多太长(我也没看完),可以看看他的这个浓缩版的演讲,该演讲把 future, promise, async, then 等方方面面都讲到了。个人小小的体会,async 加上 lambda,你会发现 c++ 里写 non-blocking code 忽然变得这样直接和容易,简直不敢想像。
另外就是关于 coroutine,微软的人在 cppcon2014 上展示了一个在 vc 中实现的 await2,貌似和 c# 中的 await 有些关联??从他们的演讲来看,await2 可以 stackless,因此 highly scalable, 细节是怎样的,十分值得细究,基于 await 的编程看起来又完全不同的感觉了,很多其它高级语言里特性逐渐地出现在了 c++ 里面。
lambda 并不是一个新的东西,就算在 c++11 中,它的出现也这样地顺理成章,甚至可以认为不过就是 functor 的语法糖,但是它的诞生在很多情况下却让写代码变得这样的简单直接,以致如果你深入体验之后,已经完全没法再脱离它,前面 Sean Parent 关于 concurrency 的演讲里面就有很多这方面的例子,另一个活生生的例子可以参看一下 Andrei Alexandrescu 的这个演讲: systematic error handling in c++,看看 lambda 是怎样使得 scope guard 在 c++11 里的实现变得这样简洁与实用。说到 scope guard,如能灵活地使用起来,这东西的确在很多时候可以使得程序的控制流更直接更可读,看看 Andrei 在 cppcon 上的这个演讲。
对于模板,变长参数的加入极大地简化了模板元编程,以前很多需要使用许多死板的宏技巧才能实现的功能,现在已经可以很轻松地用 variadic template 来实现了, 这里有一个入门的教程,Andrei Alexandrescu 也在这方面有一个演讲(这个题目怎么少得了他):Variadic Templates are Funadic,Andrei 的演讲无论是内容还是风格一如既往让人倾倒,鼓励大家前去围观。除了变长参数,c++11 中也加入了一系列其它的模板基础设施,比如更加丰富的 type traits, SFINAE 等,c++ 委员会里一位资格极老的成员 Walter Brown 在 cppcon2014 上作了一个这方面的演讲,不过这里面主要侧重在 SFINAE 了。
说到模板,回想起一年前使用 boost spirit 和 boost proto 所经受的彻底洗礼与摧残,现在仍觉受益匪浅,我觉得喜欢搞模板的人不尝试一下 expression template, 不玩一下 proto 那他的人生是不完整的,cpp-next 有 proto 的作者 Eric Niebler 写的一系列文章:Expressive C++(如果打不开,尝试这个备份的镜像,十分值得一读,如果读了一两遍没搞懂,没关系,多看几遍,你可能会发现还是没完全搞懂也不奇怪, 看过这一系列文章,如果你还有兴趣,cppcon2014 上还有一个更好玩的,HANA: EXPRESSIVE METAPROGRAMMING,enjoy.
最近在 cppcon2014 上发现了一个挺有意思的项目,也是和模板相关的,sqlpp11,这个项目利用 expression template 在 c++11 基础上实现了一个 sql library,创意程度直逼 boost spirit,关键是,它相当地实用,因此实在值得学习借鉴。
最后是关于 functional,是的,functional programming,一听就高大上,buzzword 火热如同当红炸子鸡,functional programming via c++ 也许有点牵强,functional programming via c++11,看起来却有所不一样了,practical functional programming,看看别人都在想什么都在玩什么。。。其实话说回来,这些都不新鲜,boost 库中相关的库 fusion 和 phoenix,已经存在很长一段时间了,只是你关注到了没有而已。
TODO