1. 程式人生 > >【C++ STL應用與實現】0: 感恩STL——STL, ACM和年輕的我們

【C++ STL應用與實現】0: 感恩STL——STL, ACM和年輕的我們

本系列文章的目錄在這裡:目錄. 通過目錄裡可以對STL總體有個大概瞭解

前言

本文是一篇洗腦文,鼓吹STL的好處, 回憶作者第一次認識STL,並給出STL的學習路線。

初見STL

第一次接觸STL還是在我的大學時代,大一下學期剛剛學完了C++, 真的僅僅是把C++當做“帶類的C”來使用,對當時的我來說C++只是比C多了個class,多了個繼承和virtual,寫一些Circle和Rectangle繼承自Shape之類的玩具作業,感覺沒什麼吊炸天的感覺。當老師佈置《資料結構》期末的課程設計作業的時候,我還傻傻的選了用C語言設計一個行編輯程式。直到一次有個同學發給我一個C++的程式,他在網上下的想自己改改作為課程設計但不會改,就讓我幫他改。我一看main.cpp也傻了,這開頭的一堆#include

是啥?

#include <vector>
#include <algorithm>
#include <functional>

印象最深的是一句程式碼裡有:for_each(files.begin(), files.end(), mem_fun(&File::print))

“這是在搞啥?”

稍微看一眼File的定義,奧,明白了(STL之所以好,還在於其使用和表達方式的直白,新手都很容易理解), 這是在遍歷容器裡的File指標,並呼叫它的成員方法print。我當時心裡的想法是:“cao,還可以這麼寫C++?好牛!” 於是開始百度搜索(那時候第一想法還不是用google -_-)for_each, algorithm, mem_fun, functional … 。

終於知道在C++語言中還有這麼一座寶藏,好tm激動。從圖書館借回來那本醜醜的灰綠色的《C++標準程式庫》(侯捷譯)第一版(人氣不高, 好幾本都沒人借), 看這本書的時候經常看到高潮迭起。印象最深的是有一節講到容器和演算法的配合,可以用兩行程式碼實現從輸入流讀取一堆字串,排序,輸出,我靠,簡直不能更酷:

#include <iostream>
#include <set>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std
; int main() { set<string> coll((istream_iterator<string>(cin)), (istream_iterator<string>())); copy(coll.begin(), coll.end(), ostream_iterator<string>(cout, "\n")); return 0; } // 提示初學者:你在測試這段程式碼時,輸入字串的時候,回車分隔不同的字串,在windows上用ctrl + z來結束輸入. linux上用ctrl+d結束

還有一個例子是那本書的作者用來展示STL威力的程式碼,用三條語句實現從輸入流讀取一堆字串,排序,去掉重複,並輸出:

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;

int main() 
{
    vector<string> coll;

    // 讀取字串,直到EOF(windows上使用ctrl+z輸入) ,逐個插入到coll的結尾
    copy(istream_iterator<string>(cin), istream_iterator<string>(), back_inserter(coll));

    // 字串排序
    sort(coll.begin(), coll.end());

    // “唯一化”輸出到標準輸出流
    unique_copy(coll.begin(), coll.end(), ostream_iterator<string>(cout, "\n"));

    return 0;
}

從此以後,STL在方便我生活的同時也成為了我的一個裝b利器,

LifeIsBoringWithoutZB.jpg

每當遇到誰讓我幫忙寫程式碼的時候, 尤其是知道他大概不認識STL的時候,我必須在程式碼裡“強行”使用STL,就為了能夠讓他在看到程式碼時候,有種: “cao,這是啥, 這tm是啥…?跟這小子比,我的C++真是白學了。”的想法。

STL與ACM

後來開始參加ACM比賽,拿了省賽和東北賽區的獎,可以說STL至少有一半的功勞。

每次參加練習賽和正式比賽,我都必須隨身攜帶那本厚厚的灰綠書,就為了看STL到底有沒有為我提供想要的介面來解決手頭的問題。就在這種現學現賣的情況下,我慢慢的加深對STL的瞭解。比賽中不僅對解題時間有限制,同時對程式的時間複雜度和空間複雜度也都有限制,這也強迫我開始去關心STL的時間和空間複雜度問題,開始關心STL的實現方式。

到了參加省賽的時候,我基本上已經可以做到不看書,熟練的使用常見的STL容器和演算法了。還記得省賽的最後5分鐘,我們只AC了3道題,排名幾乎已確定不能參加東北區賽了。我和兩個學弟最後一起看一道題,經過我們仨討論,突然發現我一開始理解錯題意了,這道題很簡單,我們馬上有了思路,我們仨相互對視了一眼

(我們三個配合很默契,大一數學系的學弟負責分析數學類的難題, 或者寫出公式,或者把思路描述給我; 大二軟體工程的學弟負責綜合類的問題分析,我由於更熟悉C++且敲程式碼速度很快,所以負責所有的程式碼編寫和程式碼提交大權, 剛開始我先集中精力快速搞定簡單題, 之後加入到他倆的分析工作,進度卡住時候大家就聚在一起研究問題,解決方案確定之後,我就把大家的想法翻譯成C++程式碼、提交,然後三個人一起心臟狂跳, 撲通撲通撲通。。。)

, 他倆的眼神在說,“哥,我相信你”。我扯過鍵盤,在檔案的開頭加上一行 #include <set>之後,開始噼裡啪啦一頓狂敲,賽場裡其他隊伍嗡嗡的討論聲和我緊張的心跳聲混雜在一起,那感覺像是在做夢, 撲通撲通撲通。。。我能感覺到他倆像我一樣,心臟也撲通的不行。大概不到三分鐘後,編譯&通過了題目的示例輸入。沒時間做邊界測試了,我把程式碼貼到輸入框,點選了submit。在這評判結果返回的幾秒鐘裡,他倆左右手分別搭在我的肩膀上,我們仨就像在看世界盃決賽中隊友主罰最後點球時候一樣緊張。

幾秒鐘後,提交列表裡我們看到了醒目的 “Accepted”, 在確認了確實是我們的提交之後,我們仨幾乎是在同一時刻喊出來:“yeah!”, 不顧其他人詫異的目光,我們相互摟了摟肩膀,總算沒有遺憾了。最後我們獲得了省賽second prize並晉級了一個月後東北賽區的比賽。雖然這個成績相對於那些ACM大牛來說太過一般,但是在這個過程中我們的成長是獎金和獲獎證書所無法比擬的。而當時激動的最後五分鐘,幫助我們晉級的正是STL,最後那道題我運用了std::set保持元素唯一且有序以及O(logn)的查詢時間這些特性,才在不到三分鐘內快速搞定了問題。

C++11, C++14, C++17… 不,你tm等等我。

時光飛逝,眨眼間我已工作了好幾年,STL伴隨著C++11標準的釋出有了比較大的變化,《C++標準程式庫》第二版也已出版,我沒有等到中文版的出版,慢慢啃著英文版的第二版。雖然沒有看第一版時候那麼激動,但看到STL變得更好用,心理還是很開心。我正在做到熟練運用STL這條路上穩步前行,希望我學習的速度能趕得上它發展的腳步。 我發現,把學到的東西寫出來,描述出來,能加深對知識的理解和記憶,同時還能給初學者帶來一個參考,也算自己為STL技術的發展和普及盡一份綿薄之力,作為它給我巨大幫助的回報。因此,我要把對STL的學習和應用總結出來,提高自己同時也給想了解STL的人提供參考, 希望STL能給更多人帶去初見時那種“激動到尿褲子”的快感 ;)。

提到學習STL就不能不提到侯捷老師對學習STL劃分的三個境界:

境界一:熟用STL

境界二:瞭解泛型技術內涵和掌握STL的原理及實現

境界三:擴充STL

有很多牛b的人,牛b的公司覺得STL不好用,甚至因為記憶體碎片、執行緒安全之類的問題在專案中明令禁止使用STL,自己來寫或定製STL,也有測試資料表明,他們自己寫的庫確實在效能上會超出STL很多,某些特性甚至相差幾個數量級。這些人已經站到了第三個境界裡,我在第一境界裡仰望著他們,同時希望自己早些達到他們的境界。

STL學習路線

最後分享一個《C++標準程式庫》上的STL和C++泛型程式設計的成長路線圖:以要讀的書來看,

1《C++標準程式庫》-->2《Effective STL》-->3《Generic Programming and the STL》-->4《STL原始碼剖析》-->5《Modern C++ Design》-->6 《C++模板超程式設計》

第1, 2本都看完了,再多加練習,第一個境界就算OK了,就能升級了。

第3, 4本看完了,再多加實踐、思考就算第二個境界合格了。

第5本,就開始教你怎麼玩STL了,讓你離第三境界更近一步。至於怎麼升到第三境界,我想還是需要自己多思考實踐吧,從量變到質變。

第6本是我加上去的,模板超程式設計就開始告訴你怎麼玩轉C++編譯器了,讓你的程式碼跑在編譯時而不是執行時,教你用編譯時多型,而不是執行時多型。你要寫出能控制程式碼的程式碼,生成程式碼的程式碼。有點人工智慧的感覺。

因為C++標準更新的原因, 如果不想停留在C++98時候的STL,你就得再看一些C++11或者更新標準的書,推薦《深入理解C++11新特性》這本書,由C++標準委員會成員和IBM C++編譯器設計團隊共同撰寫,質量保證。最近祁宇也出了一本C++工程實踐方面的書,值得一看。國內的C++新標準的書並不多。

下面這幾個C++連結非常有用,C++語言和STL的官方參考.

作者水平有限,對相關知識的理解和總結難免有錯誤,還望給予指正,非常感謝!

歡迎訪問github部落格,與本站同步更新