簡介
經典的數據結構數量有限,而傳統的編程技術為了適應不同數據結構的變化,在實現向量、鍊表等結構和插入、刪除、排序等操作時,需要大量編寫重複或類似的代碼。而標準模板庫 ( Standard Template Library,STL) 允許我們重複利用成熟的代碼去構造自己的特定類型下的數據結構。通過設定模版類,STL 提供了最常用的數據結構和算法。這些模板的參數允許我們指定對象中元素的數據類型,可以簡化重複性的編程工作,顯著提高代碼的可讀性,並極大的降低維護的難度。
STL 是 C++包容類庫,提供了許多常用的基本算法和數據結構。作為 C++語言的新組成部分, STL 引入了基於泛型編程的概念。泛型編程是一種無須考慮特定對象的描述方法,它與具體數據結構無關。STL 又是通用類庫,其中的構件幾乎都由模板類或模板函式實現。由於模板具有較好的可重用性和可擴展性,可以利用 STL 來實現效率很高的代碼。使用 STL 可以快速地實現如下功能:創建有序的鍊表對象;創建共享單個鍵的有序關聯鍊表對象;用簡單、直接的方式操縱複雜數據結構;用預先定義的算法對存放在容器中的信息進行複雜的操作。
組成
STL 主要由容器 (Container)、疊代器 (Iterator) 和算法 (Algorithm)等三部分組成:
容器是 STL 的主要組成部分之一,用以實現存放和管理其他對象等功能。當程式涉及較為複雜的數據結構時, 利用容器對眾多複雜的對象進行管理, 可以避免操縱大量獨立的對象。容器僅按一定的數據結構存放和管理內部的對象, 而不會涉及到對象內部的數據。
疊代器相當於連線數據結構( 容器) 和算法的中間層,提供了對容器中對象的安全可靠的訪問方法, 並且定義了容器中對象的範圍, 其作用類似於指針。每一個容器都定義了自身專有的疊代器,用以存取容器中的元素。
算法。模板的特點之一是允許直到對模板進行特化的時候才對數據類型作出選擇。STL 利用模板的這個特點,提供了大約 100 個實現算法的模板函式。只要通過調用算法模板,就可以完成所需的功能,因而許多代碼可以被極大的化簡,編碼效率顯著提高。同時,每個函式在很大程度上都是獨立的,即不僅可以用於向量、列表等容器,也可以用於常規的數組。常用的功能包括: 比較、交換、查找、遍歷、複製、修改、刪除、排序、歸併等操作。
歷史
標準模板庫系由Alexander Stepanov創造於1979年前後,這也正是比雅尼·史特勞斯特魯普創造C++的年代。
雖然David R. Musser於1971年開始即在計算機幾何領域發展並倡導某些泛型程式設計觀念,但早期並沒有任何程式語言支持泛型程式設計。第一個支持泛型概念的語言是Ada。[來源請求] Alex和Musser曾於1987開發出一套相關的Ada library.
標準模板庫設計人Stepanov早期從事教育工作,1970年代研究泛型程式設計,那時他與其同事一起在GE公司開發出一個新的程式語言——Tecton。
1983年,Stepanov先生轉至Polytechnic大學教書,繼續研究泛型程式設計,同時寫了許多Scheme的程式,套用在graph與network的算法上,1985年又轉至GE公司專門教授高階程式設計,並將graph與network的Scheme程式,改用Ada寫,用了Ada以後,他發現到一個動態(dynamically)類型的程式(如Scheme)與強制(strongly)類型的程式(如Ada)有多么的不同。
在動態類型的程式中,所有類型都可以自由的轉換成別的類型,而強制類型的程式卻不能。但是,強制類型在出錯時較容易發現程式錯誤。
1988年Stepanov先生轉至HP公司運行開發泛型程式庫的工作。此時,他已經認識C語言中指針(pointer)的威力,他表示一個程式設計師只要有些許硬體知識,就很容易接受C語言中指針的觀念,同時也了解到C語言的所有數據結構均可以指針間接表示,這點是C與Ada、Scheme的最大不同。
Stepanov並認為,雖然C++中的繼承功能可以表示泛型設計,但終究有個限制。雖然可以在基礎類型(superclass)定義算法和接口,但不可能要求所有對象皆是繼承這些,而且龐大的繼承體系將減低虛擬(virtual)函式的運行效率,這便違反的前面所說的“效率”原則。
到了C++模板觀念,Stepanov參加了許多有關的研討會,與C++之父Bjarne討論模板的設計細節。如,Stepanov認為C++的函式模板(function template)應該像Ada一樣,在聲明其函式原型後,應該顯式的聲明一個函式模板之實例(instance);Bjarne則不然,他認為可以透過C++的重載(overloading)功能來表達。
幾經爭辯,Stepanov發現Bjarne是對的(引用侯俊傑《標準模板庫講座·第三章》)。事後Stepanov回想起來非常同意Bjarne的作法。
“ template 引數推導機制(arguments deduction ,在標準模板庫中占非常重要的角色。Alexander Stepanov(標準模板庫創造者)在與Dr. Dobb's Journal進行的訪談中說道‘1992 我重回generic-library的開發工作。這時候C++有了template
我發現Bjarne完成了一個非常美妙的設計。之前我在Bell Lab曾參與數次template的相關設計討論,並且非常粗暴地要求Bjarne應該將C++ template設計得儘可能像Ada generics那樣。我想由於我的爭辯是如此地粗暴,他決定反對。我了解到在C++中除了擁有template classes之外還擁有template functions的重要性。然而我認為template function應該像Ada generics一樣,也就是說它們應該是顯式實例,Bjarne沒有聽進我的話,他設計了一個template function機制,其中的template是以一個重載化機制 (overloading mechanism來進行隱式實例這項特殊的技術對我的工作具有關鍵性的影響,因為我發現它使我得以完成Ada不可能完成的許多動作。我非常高興Bjarne當初沒有聽我的意見。’(DDJ 1995 年三月號)”。
事實上,C++的模板,本身即是一套複雜的宏語言(macro language),宏語言最大的特色為:所有工作在編譯時期就已完成。顯式的聲明函式模板之實例,與直接透過C++的重載功能隱式聲明,結果一樣,並無很大區別,只是前者加重程式設計師的負擔,使得程式變得累贅。
1992年Meng Lee加入Alex的項目,成為另一位主要貢獻者。
1992年,HP泛型程式庫項目結束,小組解散,只剩下Stepanov先生與Meng Lee小姐(她是東方人,標準模板庫的英文名稱其實是取STepanov與Lee而來[2]),Lee先前研究的是編譯器的製作,對C++的模板很熟,第一版的標準模板庫中許多程式都是Lee的傑作。
1993年,Andy Koenig到史丹佛演講,Stepanov便向他介紹標準模板庫,Koenig聽後,隨即邀請Stepanov參加1993年11月的ANSI/ISO C++標準化會議,並發表演講。
Bell實驗室的Andrew Koenig於1993年知道標準模板庫研究計畫後,邀請Alex於是年11月的ANSI/ISO C++標準委員會會議上展示其觀念。並獲得與會者熱烈的回應。
1994年1月6日,Koenig寄封電子郵件給Stepanov,表示如果Stepanov願意將標準模板庫的幫助文檔撰寫齊全,在1月25日前提出,便可能成為標準C++的一部分。Stepanov回信道:"Andy, are you crazy?" 。 Koenig便說:"Well, yes I am crazy,but why not try it?"。
Alex於是在次年夏天在Waterloo舉行的會議前完成其正式的提案,並以百分之八十壓倒性多數,一舉讓這個巨大的計畫成為C++ Standard的一部分。
標準模板庫於1994年2月年正式成為ANSI/ISO C++的一部分,它的出現,促使C++程式設計師的思維方式更朝向泛型編程(generic program)發展。