C++ 如何進階?

本人有C基礎。C++語法知識學過一遍,現在不知道如何進階學習,提高能力。是要繼續看書?自己創造項目?參加開源項目?


這是我為琪石職業發展俱樂部(http://qishicpc.com)寫的文章,主要針對在美國金融業需要C++的Quant或developer職位寫的指南,再發一次,希望有所幫助。


1.C++的用途和意義

總體來說,C++作為一門軟體開發語言,它的流行度是在減少的。主要原因在於語言的複雜和靈活導致軟體開發成本提高,這體現在開發周期和人力上。它不適用於startup公司的快速開發,也不適合用於普通的對性能要求不高的軟體系統中。C++的優勢體現在語言的靈活和對底層的控制,比如內存分配和釋放,和其他硬體的交互能力上,這導致在對性能要求高的系統中它能夠體現價值,在金融業常用於兩類系統,衍生品定價系統(包括風險控制的計算系統),以及低延遲交易系統。這也是為什麼金融行業對Quant常常要求C++的原因。因為C++用途的局限,一般建議程序員應多學一些其他語言,如Python, JavaScript, R, Java, Scala等。


2. C++入門

C++入門最推薦的書是C++ Primer (注意,不是C++ Primer Plus) ,或者The C++ Programming Language,二者選一即可。讀之前最好已經有一點編程的基礎,不管什麼語言。這些書內容很多,應該側重於理解概念,而非單純記憶。重要的概念理解後自然會記住,一些不是很重要的概念一時記不住也沒有關係。C++的概念和規則很多,就算是有經驗的C++程序員有時也需要google一些語言規則。在這個階段應該掌握重要的概念。

這一階段以後可以思考下面這些問題。

Difference between pointer and reference?

i++, ++i, which one is better?

Why use virtual destructor?

What is the signature of a copy constructor/ assignment operator?

How to specialize a class template?

What are the four types of casts in C++? Usage?

etc.


3. 演算法和數據結構

對C++來說,首先要了解Standard Template Library中提供的數據結構的複雜度以及常見的實現。了解各種演算法,可以參考演算法導論CLRS前17章,Cracking coding interview等書,這些書所採用的語言並不重要,主要是了解演算法。Leetcode的easy和median難度的題目可以用來練習。可以思考的問題有:

What does reserve() do on std::vector? What is the complexity of adding element to a std::vector?

Underlying data structure of std::map/std::unordered_map? Implementation outline.

K-way merge sort.

How would you implement atoi and itoa functions?

Max sum subarray problem.

How to compute max drawdown of a price time series?


4. C++進階

可以閱讀Effective C++, Effective STL, C++ FAQ(website) 和一定編程規模(數千行代碼量)的project。只有在Project中才能真正學習。C++ standard library 的實現也是很好的學習工具。它有幾個不同的實現,GCC, SGI, Clang等。Clang的實現比較清晰,如果用GCC作為編譯器的話了解GCC的實現對有效使用library中的container是很有好處的。對於Quant來說不一定要掌握到這個部分所提到的內容,有興趣的話可以學習。


這個階段以後可以思考下面這些問題。

What is strong exception guarantee? Cost of exception handling? Why C++11 deprecate exception specification?

What is type trait?

What is smart pointer? Difference between std::shared_ptr& and boost::instrusive_ptr&? Implementation outline.

How is virtual function call implemented? What is the cost of virtual function calls? *What is CRTP? *What is the limitation of that?

*What is the runtime cost of a lambda function? *What is the cost of std::function compare to a function pointer? *What does std::function gain from that cost?


注1:帶*號為難度較大的問題,Quant或初學者可以不在這上面浪費時間

注2:本文所提的思考問題僅是一些有代表性的問題,僅代表C++知識的一小部分。


5. C++11

C++ Primer第五版已經涉及,另外還有Effective Modern C++. C++11很重要,有很多改進需要了解和掌握,在程序中善於使用。這裡舉一些比較有代表性的, move sematic, rvalue reference, range based for loop, override keyword, static assert, initializer list, lambda, etc. Boost library的最常用內容已經包含在C++11中,建議先掌握C++11再關注Boost的其他內容。


6. 軟體開發環境

  • Version control. Git是主流,在老的開發組裡可能還在使用SVN或者CVS。這是團隊開發必須掌握的工具。

  • Testing. production code的設計要考慮到其可測試性,所有的代碼在release之前都要經過測試。測試的設計,自動化等工作也是需要功夫的。

  • Build system. 常見的C++ build system有Make, CMake, Automake, scons, Visual Studio等,至少會使用一種。了解Gcc的使用,了解如何使用第三方庫。

  • Debugging/Profiling tool: Valgrind memcheck, Cachegrind, gprof, OProfile, etc.

7.行業相關:衍生品定價系統

這樣的系統以計算為核心,需要數值計算,並行計算的知識。現在GPU也比較流行,一般使用nVidia的CUDA. 並行計算也有使用MPI的。另外系統的跨平台特性和其他系統和語言的介面也是開發的要點之一。


8.行業相關:低延遲交易系統

交易系統注重對底層的了解。Memory alignment, multithreading, networking communication, cache friendliness, 如何保證系統的高可靠性,這些都是值得注意和學習的地方。建議學習SEC對Knight Capital trading error事件的調查報告https://www.sec.gov/litigation/admin/2013/34-70694.pdf, 以及SEC對Tower Research RegNMS violation的調查報告http://www.sec.gov/litigation/admin/2015/34-76029.pdf. 以及知乎大神董可人的文章C++ 為核心語言的高頻交易系統是如何做到低延遲? - 董可人的回答 和高頻交易軟硬體是怎麼架構的? - 董可人的回答


C++需要不斷地練習——by @vczh


C++語法知識學過一遍?
理解與否?能不能靈活運用?

我想,以你目前的狀況,
一個可行的方法是,自己設計一個項目(做個具有一定使用價值的軟體,不一定非要用GUI界面,比如,根據某個關鍵詞在多篇文檔中的比率進行排序)
然後在項目中實踐和運用自己學到的C++語法知識,積累經驗

等到有了一定的經驗之後,再去更大範圍的實踐,可以到公司實習,也可以參加開源項目,方式有很多。
===============
補充,想起一位老師說的:
書看千行不如手敲一行! 手敲千行不如單步一行! 單步源代碼千行不如單步對應彙編一行!太贊了


來看看 C++ 入門到精通都要掌握什麼技能。


該看的書有人給你推薦了。實踐才是王道,有功夫你試著把你熟悉的用C寫的程序用C++改寫一段,從這幾個方面來反問一下自己:

1. 運算性能有何變化;可以編寫一個小程序來測測,或者用其他性能檢測工具判斷一下。
2. 複雜度有無增加?例如原來通過全局函數、變數處理的事情現在都放到類中,有何工作量的增加?
3. 程序閱讀和維護起來是否方便了。不要覺著C++就一定能增加可維護性,閱讀起來更爽,你寫不順流照樣讓你自己暈菜。

接下來,你思考一下虛函數在編譯器內部做了哪些動作,它讓程序的動態和靜態載入執行會對系統帶來哪些影響?
為啥需要模板?什麼樣的模板可以被收納進STL這樣的優質庫?如果為你自己的公司或項目做一套值得稱為模板的東西,你的程序里需要有哪些考核點?

等你對這些問題有了深刻和實踐的體會,我相信,至少您的C++水平可以參與干大一點的項目了。
先寫這麼多,明兒接著聊。


精通C++和超光速一樣,目前是個偽命題


如果你真的想要C++進階
Modern C++ Design
http://freemind.pluskid.org/programming/policy-based-programming/

不過我的建議是等幾年再學C++吧.....


抓緊時間看點有用的東西。內核啊,TCP/IP 啊。Cocoa,Win32,OpenGL 啊。編譯器啊(ANTLR)。虛擬機啊(Lua,Python)。

C++ 可以抽空看看《The Design and Evolution of C++》,別整什麼「進階」這種沒用的東西。


語法已經學完了的話,下面就自己多寫吧。可以先寫一些GUI程序練習,再往後練習更多偏系統編程層面的。
C++主要的應用場景還是在需要高性能的系統編程,因此進階的另一部分就是加深對計算機系統組成結構的理解。


點擊看大圖

這幅圖的英文原作的出處有誰知道么 國內的譯者也查不到了

Update:
感謝@御宅暴君 指出原圖出處 http://abstrusegoose.com/249


  • C++ Programming Language
  • Effective Modern C++
  • The C++ Standard Library: A Tutorial and Reference
  • Modern C++ Design: Generic Programming and Design Patterns Applied
  • C++ Templates: The Complete Guide
  • Memory Management: Algorithms and Implementation in C/C++
  • Memory as a Programming Concept in C and C++
  • C++ Concurrency

我也是很早就學習了基礎C++知識,然而發現前面是「斷崖」而無法前進的編程者。
我認為以上回答都站在已經全面把握C++編程理念的熟練人員立場上,並沒有回想起初學C++時的痛苦經歷。編程思想或者是「學會了基本語法之後,開始研究現有代碼」,以及"自行優化代碼」,源碼剖析之類,這對於初學者是難以接受的,特別是看到大段大段幾乎全是用大寫英文的消息句柄的源代碼時的挫敗感,很容易打擊初學者。


實際上,大部分的C++書籍不是入門階段(介紹變數指針基本流程……一直到類、繼承、對象之類的抽象概念,而且只有命令行程序)就是大牛階段(各種大型程序,庫的使用),唯獨中間少了一段windows下的可視化編程(尤其MFC),消息、框架化模式、以及數據應用的過渡教程。

我推薦這本書:21天學通Visual C++ (豆瓣) 【請不要鄙視「21天」這樣急功近利的字眼,這恰好說明了書的易讀性】
這本書是在學校圖書館搜到的,在一大堆亂七八糟的標準教程和代碼五百例之間,終於發現一本用來進階的書籍。
我不清楚編程大牛們是怎麼學的(也有可能真的自行啃代碼,完成了編程能力的大跳躍),然而我們需要的是一個通用的、可以循序漸進、明白實用的方法。這本書能夠提供以上這些。


居然還有哥們跟這兒貼面試題的……


輪子以前說過,C++就是你拿出一本書,從頭看完能理解理解,不能理解背下來。然後不停的實踐,遇到了,就會想起來,然後就真明白了。

張佳瑋在一篇文章里也提過讓小孩子從小看很多書有什麼好處。他舉得是謝遜逼張無忌死記硬背武功口訣的例子。你今天不懂沒關係,硬記下來,時候到了,會一下融會貫通,水到渠成。

scott meyers那四本書對於「有C基礎,學過C佳佳語法的人」暫時還用不著,而且時代進步了他第一本書的內容在primer第五版里很多都包含了。

通讀primer第五版,例子盡量敲一遍。然後就是不停的實踐。不推薦C佳佳他爹出的哪本書,惜字如金,寫的像使用手冊…

任何語言的「進階」,其實都是software engineering能力的進階。其實也就是所謂的system design的能力。數據結構和演算法要學好這種人盡皆知的東西不用提你也該知道。其實所謂數據結構和系統設計,仔細想想,本質上一回事。

engineering的能力的晉陞沒什麼書教的,自己也悟不出來,就是多看別人的代碼和自己寫。

github的項目很多都是解決問題的,需要很多特別知識,你需要額外看syscalls,http等知識。我個人的經驗和建議就是圖形學那三個演算法,raytracing,radiosity,photomapping。實現細節上要繼承有繼承,要多肽有多肽,要template有template。而背景知識,只要數學。

一個字,寫寫寫。踏踏實實寫幾個大程序。天天研究++i和i++這類問題沒什麼前途。你見有誰說初始化時必須 int a(5) 不能 int a = 5了?技術是超越語言而存在的。

才疏學淺,發幾句妄言,匿了。


多讀書,讀好書,prime讀完,再把 effective三卷本讀讀,有興趣可以看看深入理解c++對象模型(偶爾細節有爭議,但整體還不錯,適合提高)。。
看一些c++開源項目源碼,多編碼。


基本語法看過一遍以後,就可以嘗試做項目了。如果沒有工作中的實際項目,就從網上找點源碼研究研究,自己拓展一些功能,最好是學習下優秀的開源軟體(可以只看某個模塊)。在寫代碼的同時,繼續看書學習。知識+實踐,兩手抓,進步快。


旗幟鮮明的反對c++ = c+classes 的觀點。

這種寫法正是c++的歷史包袱和障礙。特別是團隊里有大量熟悉c的人的時候:

有的人是這樣使用c++的,一個class 的函數全部靜態,然後函數直接按照c的寫法,通過傳遞大量的參數來通信,沒有class的成員。這是把class當做name space的流派。

name space的流派還有發展,這回不全是靜態函數了,但是什麼都是單例,函數繼續我行我素的c style 面向過程,這是懂設計模式的name space流派。

有的人是這樣使用c++的,一個class完全沒有函數,全部都是public member,然後通過寫大量面向過程的c style函數把object傳來傳去。這是把class當做struct流派。

struct的流派還有發展,就是不寫public member了,改成private member+getter setter,然後繼續大量面向過程的c sytle函數,這可能是看過兩天java的struct流派。

如果你這樣用c++,為什麼不直接用c呢。

c++提供了大量的feature,因此精通它是困難的,很多feature你可能很久都不會用到,但是不等於,你就一個都不用了,那樣不如直接c啊。

c++是個倉庫,裡面雖然凈是些核動力動力錘,核動力改錐這種難於掌握的東西,但是不代表你要把動力錘的電源關掉,把它當普通鎚子用。所謂c++的進階,便是從這倉庫里選出合適你的任務的工具並把它耍的飛起。

我認為的進階之路:知道有哪些鎚子&>知道鎚子的特點&>能選擇正確的鎚子&>將正確的鎚子使用正確


我是個比較奇葩的人,入門之前沒有任何基礎(包括中學數學基礎),直接就上了Accelerated C++,後來又看了同一個人寫的Ruminations on C++還有著名的Effective C++,去年才抽時間看的C++ Primer Plus,前一段時間為了進階又看的C++ Templates。用的來說看看書沒錯,但不如給自己找點有難度的項目,不會的就買書看或者翻翻知乎和CSDN,沒事去翻翻CppReference,總的來說光學不做根本沒用。


while(1){
C++;
}


說真的,找幾個你覺得寫的很好的開源c++項目研究研究最靠譜,其他的書瀏覽一下就差不多了,你能背的下來?知道遇到問題哪裡能找到答案很重要,說實話,中國現在的環境,多接觸java,c#是正途,最流行什麼就去學什麼,畢竟只是一個工具,c++圈子縮小只是時間問題


主要還是多讀一點經典書籍,如primer,深度探索C++對象模型等書,你不看書直接取看項目你根本就抓不到點,讀書配合項目這樣才能學到更多更精華的東西!


推薦閱讀:

徒手碼一千行以上代碼是一種怎樣的體驗?
如何系統地學習 C++ 語言?

TAG:編程 | C++ | 編程學習 |