最近一段時間 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 上:
- Atomic<> weapon, 1, 2, Herb Sutter.
- Threads and Shared Variables in c++11, Hans Boehm.
看完前面兩個視頻,估計就能對 c++11 里的 threading 和 atomic 相關的庫有大概的了解,不過與此同時估計讀者腦海里也多了一堆對技術細節的疑問,尤其是 ordering 相關的,此時可以再去看看以下兩個長篇,其中一篇是講硬件實現上的細節,a primer on memory consistency and cache coherence,另一篇則介紹了 linux 內核中 memory barrier 的相關知識與背景
如果你實在很好學,追求極致細節想成為 language lawyer 什么的,這里幾個鏈接,分別是 Hans 和 Herb 當初給 c++ 委員會作的原始提案,細看一下就能知道現在 c++11/14 里相關內容的是怎么來的:
- Boehm, Hans. A Memory Model for C++: Strawman Proposal
- Boehm, Hans. An Atomic Operations Library for C++
- Sutter, Herb. Prism: A Principle-Based Sequential Memory Model for Microsoft Native Code Platforms
上面的鏈接都來自權威人士,其中文章大多非常嚴謹因而可能不夠通俗易懂,國外有一位叫 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)
Threading/concurrency####
語言級別的並發編程也許是 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、模板、函數式####
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