當前位置: 華文星空 > 體育

Boost裏已經有的輪子一定要自己造是一種怎樣的心態?

2017-09-05體育

我一直非常喜歡boost,自從2004年無意中發現它。當時我就驚呆了,心裏想如此龐大完整的程式庫,只要學會了它,一輩子都夠用了。

從那以後我一直對boost保持關註,也用它來開發一些小工具,每次boost升級,我都會第一時間更新,從源碼經過漫長的編譯升級以後,渾身上下一陣神清氣爽的感覺,仿佛我自己也經歷了一次蛻變。

多年以後我有機會從頭做一個計畫,作為負責人自己尋找解決方案,在第三方庫的選擇方面,我最終放棄了boost,而且至今一直禁止在我的團隊中使用boost。

效能問題

boost的某些庫有效能問題,比如說boost::format比snprintf慢20甚至30倍以上。當然不是說boost::format就不能用了,要看場合,比如說客戶端程式,呼叫頻率不高,就可以用,而伺服器端程式,呼叫頻繁,就不適合了。

boost裏面效能不佳的庫肯定不止這一個,每次在自己使用之前最好都做一下效能測試,看看是否滿足自己的需求。當然這個測試就要花點時間了,而且每次升級到新版本,都要測試一下。boost升級蠻頻繁的。

too old

boost的強項是跨平台,並且支持N個編譯器,甚至支持一些古老的編譯器。為了支持那些古老的編譯器,boost程式碼裏面用了無數宏。但是C++11出來以後,很多特性使得編寫程式庫更容易了,於是github上出現了很多比boost中同型別庫更優秀的程式庫。比如說pybind11,就比boost::python用起來方便很多,借助C++11的樣版特性,pybind11的實作也要簡潔得多。

那些bug

每個版本的Release Notes都有不少bug的更新,這說明boost其實是有不少bug的。例如某個版本Release Notes關於某個庫的部份內容:

Fixed bugs: Trac #11627: "small_vector<T,n>::swap() appears to be broken". Trac #11628: "small_vector<int,n> iterates over elements in destructor". Trac #11697: "Wrong initialization order in tuple copy-constructor". Trac #11698: "Missing return statement in static_storage_allocator". GitHub #29: Doc fixes for flap_map complexity requirements. GitHub #31: DL_SIZE_IMPL also dereference addr.

類似這樣的東西不少,看得眼花繚亂,或許有些是和平台有關的,我們的gcc沒有碰到,也或許某些bug相關的功能根本不常用。但是,如何區分哪些bug對我們有影響哪些沒有,絕不是容易的事情,況且還有發現了但是沒有被fix掉的和沒有發現的bug呢。

新舊版本的相容

我自己常常用boost來寫一些小工具,某次boost升級以後發現之前的程式碼編不過了,仔細一看,原來是用到的filesystem庫發生了介面的變更,得修改使用該介面的程式碼,改成呼叫新的函式後來才編譯透過。

還有一些其它原因全部發出來好幾千字,太長了也沒人看,就此打住了。總之對我來說,boost作為一個全家桶,會給管理和維護帶來麻煩。

其實google的c++編碼規範裏面也用了boost,但是他們是有選擇地規定只能用哪幾個,甚至只能用某個庫的某些部份的功能。如果決定要在團隊中使用boost,最好也是像這樣根據計畫需求建立一個白名單。

當然boost肯定是一個非常優秀的C++庫,我平時的很多工具依然離不開它,但是我更喜歡去學習它的源碼,造自己的輪子。boost的協程裏面的那幾個組譯程式碼,可以直接拿出來用,打造自己的協程庫;我之前也參考boost::serialize寫了一個簡單的序列化庫,只用了幾百行,因為我只需要使用部份功能而已,但是對我的計畫來說完全滿足了。

其實,用C++最大的樂趣就是造輪子,提高C++編程水平最好的方法也是造輪子。知其然並知其所以然,才能完成編程能力的蛻變。

boost也不過是一個(些)C++輪子。每個C++輪子的價值不僅僅是給別人使用,也是給其他人造輪子提供參考。不直接使用boost而是參考boost造自己的輪子這種心態,其實也是在使用boost,而且比直接使用更為徹底。