STL之父訪談錄(一萬二千字的大塊頭)---孟巖翻譯

                                                        STL之父訪談錄
1995年3月,Dr.Dobb's Journal特約記者, 著名技術書籍作家Al Stevens採訪了STL創始人Alexander
Stepanov. 這份訪談紀錄是迄今爲止對於STL發展歷史的最完備介紹, 侯捷先生在他的STL有關文章裏
推薦大家閱讀這篇文章. 因此我將該文全文翻譯如下:

Q: 您對於generic programming進行了長時間的研究, 請就此談談.
A: 我開始考慮有關GP的問題是在7O年代末期, 當時我注意到有些算法並不依賴於數據結構的
   特定實現,而只是依賴於該結構的幾個基本的語義屬性. 於是我開始研究大量不同的算法,
   結果發現大部分算法可以用這種方法從特定實現中抽象出來, 而且效率無損. 對我來說,
   效率是至關重要的, 要是一種算法抽象在實例化會導致性能的下降, 那可不夠棒.
   
   當時我認爲這項研究的正確方向是創造一種編程語言. 我和我的兩個朋友一起開始幹起來.
   一個是現在的紐約州立大學教授Deepak Kapur, 另一個是倫塞里爾技術學院教授David Musser.
   當時我們三個在通用電器公司研究中心工作. 我們開始設計一種叫Tecton的語言. 該語言
   有一種我們稱爲"通用結構"的東西, 其實不過是一些形式類型和屬性的集合體, 人們可以
   用它來描述算法. 例如一些數學方面的結構充許人們在其上定義一個代數操作, 精化之,
   擴充之, 做各種各樣的事.
 
   雖然有很多有趣的創意, 最終該項研究沒有取得任何實用成果, 因爲Tecton語言是函數型
   語言. 我們信奉Backus的理念,相信自己能把編程從von Neumann風格中解放出來. 我們
   不想使用副效應, 這一點限制了我們的能力, 因爲存在大量需要使用諸如"狀態", "副效
   應"等觀念的算法.  

   我在70年代末期在Tecton上面所認識到了一個有趣的問題: 被廣泛接受的ADT觀念有着根本
   性的缺陷. 人們通常認爲ADT的特點是隻暴露對象行爲特徵, 而將實現隱藏起來. 一項操作
   的複雜度被認爲是與實現相關的屬性, 所以抽象的時候應予忽略. 我則認識到, 在考慮一
   個(抽象)操作時, 複雜度(或者至少是一般觀念上的複雜度)必須被同時考慮在內. 這一點
   現在已經成了GP的核心理念之一.

   例如一個抽象的棧stack類型,  僅僅保證你push進去的東西可以隨後被pop出來是不夠的,
   同樣極端重要的是, 不管stack有多大, 你的push操作必須能在常數時間內完成. 如果我
   寫了一個stack, 每push一次就慢一點, 那誰都不會用這個爛玩藝.

   我們是要把實現和界面分開, 但不能完全忽略複雜度. 複雜度必須是, 而且也確實是橫陳
   於模塊的使用者與實現者之間的不成文契約. ADT觀念的引入是爲了允許軟件模塊相互可
   替換. 但除非另一個模塊的操作複雜度與這個模塊類似, 否則你肯定不願意實現這種互換.
   如果我用另外一個模塊替換原來的模塊, 並提供完全相同的接口和行爲, 但就是複雜度不
   同, 那麼用戶肯定不高興. 就算我費盡口舌介紹那些抽象實現的優點, 他肯定還是不樂意
   用. 複雜度必須被認爲是接口的一部分.

   1983年左右, 我轉往紐約布魯克林技術大學任教. 開始研究的是圖的算法, 主要的合作夥
   伴是現在IBM的Aaron Kershenbaum. 他在圖和網絡算法方面是個專家, 我使他相信高序(high
   order)的思想和GP能夠應用在圖的算法中. 他支持我與他合作開始把這些想法用於實際的
   網絡算法. 某些圖的算法太複雜了, 只進行過理論分析, 從來沒有實現過. 他企圖建立一個
   包含有高序的通用組件的工具箱, 這樣某些算法就可以實現了. 我決定使用Lisp語言的一個
   變種Scheme語言來建立這樣一個工具箱. 我們倆建立了一個巨大的庫, 展示了各種編程技術.
   網絡算法是首要目標. 不久當時還在通用電器的David Musser加了進來, 開發了更多的組件,
   一個非常大的庫. 這個庫供大學裏的本科生使用, 但從未商業化. 在這項工作中, 我瞭解到
   副效應是很重要的, 不利用副效應, 你根本沒法進行圖操作. 你不能每次修改一個端點(vertex)
   時都在圖上兜圈子. 所以, 當時得到的經驗是在實現通用算法時可以把高序技術和副效應結
   合起來. 副效應不總是壞的, 只有在被錯誤使用時纔是.

   1985年夏, 我回到通用電器講授有關高序程序設計的課程. 我展示了在構件複雜算法時這項
   技術的應用. 有一個聽課的人叫陳邇, 當時是信息系統實驗室的主任. 他問我是否能用Ada語
   言實現這些技術, 形成一個工業強度的庫, 並表示可以提供支持. 我是個窮助教, 所以儘管我
   當時對於Ada一無所知, 我還是回答"好的". 我跟Dave Musser一起建立這個Ada庫. 這是很重
   要的一個時期, 從象Scheme那樣的動態類型語言(dynamically typed language)轉向Ada這
   樣的強類型語言, 使我認識到了強類型的重要性. 誰都知道強類型有助於糾錯. 我則發現在
   Ada的通用編程中, 強類型是獲取設計思想的有力工具. 它不僅是查錯工具, 而且是思想工具.
   這項工作給了我對於組件空間進行正交分解的觀念. 我認識到, 軟件組件各自屬於不同的類別.
   OOP的狂熱支持者認爲一切都是對象. 但我在Ada通用庫的工作中認識到, 這是不對的. 二分查找
   就不是個對象, 它是個算法. 此外, 我還認識到, 通過將組件空間分解到幾個不同的方向上, 我
   們可以減少組件的數量, 更重要的是, 我們可以提供一個設計產品的概念框架.

   隨後, 我在貝爾實驗室C++組中得到一份工作, 專事庫研究. 他們問我能不能用C++做類似的事.
   我那時還不懂C++, 但當然, 我說我行. 可結果我不行, 因爲1987年時, C++中還沒有模板, 這玩
   藝在通用編程中是個必需品. 結果只好用繼承來獲取通用性, 那顯然不理想.

   直到現在C++繼承機制也不大用在通用編程中, 我們來說說爲什麼. 很多人想用繼承實現數據結構
   和容器類, 結果幾乎全部一敗塗地. C++的繼承機制及與之相關的編程風格有着戲劇性的侷限. 用
   這種方式進行通用編程, 連等於判斷這類的小問題都解決不了. 如果你以X類作爲基類, 設計了
   一個虛函數operater==, 接受一個X類對象, 並由X派生類Y, 那麼Y的operator==是在拿Y類對象與
   X類對象做比較. 以動物爲例, 定義animal類, 派生giraffe(長頸鹿)類. 定義一個成員函數
   mate(), 實現與另一個哺乳動物的交配操作, 返回一個animal對象. 現在看看你的派生類giraffe,
   它當然也有一個mate()方法, 結果一個長頸鹿同一個動物交配, 返回一個動物對象. 這成何體統?
   當然, 對於C++程序員來說, 交配函數沒那麼重要, 可是operator==就很重要了.

   對付這種問題, 你得使用模板. 用模板機制, 一切如願.

   儘管沒有模板, 我還是搞出來一個巨大的算法庫, 後來成了Unix System Laboratory Standard
   Component Library的一部分. 在Bell Lab, 我從象Andy Koenig, Bjarne Stroustrup(Andrew 
   Koenig, 前ISO C++標準化委員會主席; Bjarne Stroustrup, C++之父 -- 譯者)這類專家
   身上學到很多東西. 我認識到C/C++的重要, 它們的一些成功之處是不能被忽略的. 特別是我發
   現指針是個好東東. 我不是說空懸的指針, 或是指向棧的指針. 我是說指針這個一般觀念. 地
   址的觀念被廣泛使用着. 沒有指針我們就沒法描述並行算法.

<爲什麼C是偉大的語言> (凡是尖括號中的內容,是由souroot總結的大綱)

   我們現在來探討一下爲什麼說C是一種偉大的語言. 通常人們認爲C是編程利器並且獲得如此成功,
   是因爲UNIX是用C寫的. 我不同意. 計算機的體系結構是長時間發展演變的結果, 不是哪一個聰明
   的人創造的. 事實上是廣大程序員在解決實際問題的過程中提出的要求推動了那些天才提出這些
   體系. 計算機經過多次進化, 現在只需要處理字節地址索引的內存, 線性地址空間和指針. 這個
   進化結果是對於人們要求解決問題的自然反映. Dennis Ritchie天才的作品C, 正反映了演化了
   30年的計算機的最小模型. C當時並不是什麼利器. 但是當計算機被用來處理各種問題時, 作爲
   最小模型的C成了一種非常強大的語言, 在各個領域解決各種問題時都非常高效. 這就是C可移植
   性的奧祕, C是所有計算機的最佳抽象模型, 而且這種抽象確確實實是建立在實際的計算機, 而
   不是假想的計算機上的. 人們可以比較容易的理解C背後的機器模型, 比理解Ada和Scheme語言背
   後的機器模型要容易的多. C的成功是因爲C做了正確的事, 不是因爲AT&T的極力鼓吹和UNIX.

<c++爲什麼會成功>

   C++的成功是因爲Bjarne Stroustrup以C爲出發點來改進C, 引入更多的編程技術, 但始終保持在
   C所定義的機器模型框架之內, 而不是閉門造車地自己搞出一個新的機器模型來. C的機器模型非
   常簡單. 你擁有內存, 對象保存在那裏面, 你又有指向連續內存空間的指針, 很好理解. C++保留
   了這個模型, 不過大大擴展了內存中對象的範疇, 畢竟C的數據類型太有限了, 它允許你建立新的
   類型結構, 但不允許你定義類型方法. 這限制了類型系統的能力. C++把C的機器模型擴展爲真正
   類型系統.

   1988年我到惠普實驗室從事通用庫開發工作. 但實際上好幾年我都是在作磁盤驅動器. 很有趣但跟
   GP毫不相關. 92年我終於回到了GP領域, 實驗室主任Bill Worley建立了一個算法研究項目, 由我
   負責. 那時候C++已經有模板了. 我發現Bjarne的模板設計方案是非常天才的. 在Bell Lab時, 我參
   加過有關模班設計的幾個早期的討論, 跟Bjarne吵得很兇, 我認爲C++的模板設計應該儘可能向Ada的
   通用方案看齊. 我想可能我吵得太兇了, 結果Bjarne決定堅決拒絕我的建議. 我當時就認識到在C++
   中設置模板函數的必要性了, 那時候好多人都覺得最好只有模板類. 不過我覺得一個模板函數在使用
   之前必須先顯式實例化, 跟Ada似的. Bjarne死活不聽我的, 他把模板函數設計成可以用重載機制來
   隱式實例化. 後來這個特別的技術在我的工作中變得至關重要, 我發現它容許我做很多在Ada中不可能
   的任務. 非常高興Bjarne當初沒聽我的.

Q: 您是什麼時候第一次構思STL的, 最初的目的是什麼?
A: 92年那個項目建立時由8個人, 漸漸地人越來越少, 最後剩下倆, 我和李夢, 而且李***是這個領域的新
   手. 在她的專業研究中編譯器是主要工作, 不過她接受了GP研究的想法, 並且堅信此項研究將帶給軟件開
   發一個大變化, 要知道那時候有這個信念的認可是寥寥無幾. 沒有她, 我可不敢想象我能搞定STL, 畢竟
   STL標着兩個人的名字:Stepanov和Lee. 我們寫了一個龐大的庫, 龐大的代碼量, 龐大的數據結構組件,
   函數對象, 適配器類, 等等. 可是雖然有很多代碼, 卻沒有文檔. 我們的工作被認爲是一個驗證性項目,
   其目的是搞清楚到底能不能在使算法儘可能通用化的前提下仍然具有很高的效率. 我們化了很多時間來
   比較, 結果發現, 我們算法不僅最通用, 而且要率與手寫代碼一樣高效, 這種程序設計風格在性能上是
   不打折扣的! 這個庫在不斷成長, 但是很難說它是什麼時候成爲一個"項目"的. STL的誕生是好幾件事情
   的機緣巧合才促成的.

Q: 什麼時候, 什麼原因促使您決定建議使STL成爲ANSI/ISO標準C++一部分的?
A: 1993年夏, Andy Koenig跑到斯坦福來講C++課, 我把一些有關的材料給他看, 我想他當時確實是很興奮.
   他安排我9月到聖何塞給C++標準委員會做一個演講. 我演講的題目是"C++程序設計的科學", 講得很理
   論化, 要點是存在一些C++的基本元素所必須遵循的, 有關基本操作的原則. 我舉了一些例子, 比如構
   造函數, 賦值操作, 相等操作. 作爲一種語言,  C++沒有什麼限制. 你可以用operator==()來做乘法. 
   但是相等操作就應該是相等操作. 它要有自反性,  A == A; 它要有對稱性, A == B 則 B == A; 它還
   要有傳遞性. 作爲一個數學公理, 相等操作對於其他操作是基本的要素. 構造函數和相等操作之間的聯
   系就有公理性的東西在裏邊. 你用拷貝構造函數生成了一個新對象, 那麼這個對象和原來那個就應該是
   相等的. C++是沒有做強行要求, 但是這是我們都必須遵守這個規則. 同樣的, 賦值操作也必須產生相等
   的對象. 我展示了一些基本操作的"公理", 還講了一點迭代子(iterator), 以及一些通用算法怎樣利用迭
   代子來工作. 我覺得那是一個兩小時的枯燥演講, 但卻非常受歡迎. 不過我那時並沒有想把這個東西塞在
   標準裏, 它畢竟是太過先進的編程技術, 大概還不適於出現在現實世界裏, 恐怕那些做實際工作的人對它
   沒什麼興趣.

   我是在9月做這個演講的, 直到次年(1994)月, 我都沒往ANSI標準上動過什麼腦筋. 1月6日, 我收到
   Andy Koenig的一封信(他那時是標準文檔項目編輯), 信中說如果我希望STL成爲標準庫的一部分, 可以
   在1月25日之前提交一份建議到委員會. 我的答覆是:"Andy, 你發瘋了嗎?", 他答覆道:"不錯, 是的我
   發瘋了, 爲什麼咱們不瘋一次試試看?"

   當時我們有很多代碼, 但是沒有文檔, 更沒有正式的建議書. 李***和我每星期工作80小時, 終於在
   期限之前寫出一份正式的建議書. 當是時也, 只有Andy一個人知道可能會發生些什麼. 他是唯一的支
   持者, 在那段日子裏他確實提供了很多幫助. 我們把建議寄出去了, 然後就是等待. 在寫建議的過程
   中我們做了很多事. 當你把一個東西寫下來, 特別是想到你寫的可能會成爲標準, 你就會發現設計中
   的所有紕漏. 寄出標準後,我們不得不一段一段重寫了庫中間的代碼, 以及幾百個組件, 一直到3月份
   聖迭戈會議之前. 然後我們又重新修訂了建議書, 因爲在重新寫代碼的過程中, 我們又發現建議書中
   間的很多瑕疵.

Q: 您能描述一下當時委員會里的爭論嗎? 建議一開始是被支持呢, 還是反對?
A: 我當時無法預料會發生些什麼. 我做了一個報告, 反響很好. 但當時有許多反對意見. 主要的意見是:
   這是一份龐大的建議, 而且來得太晚, 前一次會議上已經做出決議, 不在接受任何大的建議. 而這個
   東西是有史以來最大的建議, 包括了一大堆新玩藝. 投票的結果很有趣, 壓倒多數的意見認爲應對
   建議進行再考慮, 並把投票推遲到下次會議, 就是後來衆所周知的滑鐵盧會議.

   Bjarne Stroustrup成了STL的強有力支持者. 很多人都通過建議、更改和修訂的方式給予了幫助。
   Bjarne乾脆跑到這來跟我們一起工作了一個禮拜。Andy更是無時無刻的幫助我們。C++是一種複雜
   的語言,不是總能搞得清楚確切的含義的。差不多每天我都要問Andy和Bjarne C++能不能幹這幹那。
   我得把特殊的榮譽歸於Andy, 是他提出把STL作爲C++標準庫的一部分;而Bjarne也成了委員會中
   STL的主要鼓吹者。其他要感謝的人還有:Mike Vilot,標準庫小組的負責人; Rogue Wave公司的
   Nathan Myers(Rogue Wave是Boland C++Builder中STL方案的提供商 —— 譯者),Andersen諮詢公
   司的Larry Podmolik。確實有好多人要致謝。

   在聖迭戈提出的STL實際與當時的C++,我們被要求用新的ANSI/ISO C++語言特性重寫STL,這些特性
   中有一些是尚未實現的。爲了正確使用這些新的、未實現的C++特性,Bjarne和Andy花了無以計數的
   時間   來幫助我們。

   人們希望容器獨立於內存模式,這有點過分,因爲語言本身並沒有包括內存模式。所以我們得要想出
   一些機制來抽象內存模式。在STL的早期版本里,假定容器的容積可以用size_t類型來表示,迭代子
   之間的距離可以用ptrdiff_t來表示。現在我們被告知,你爲什麼不抽象的定義這些類型?這個要求
   比較高,連語言本身都沒有抽象定義這些類型,而且C/C++數組還不能被這些類型定義所限定。我們
   發明了一個機制稱作"allocator",封裝了內存模式的信息。這各機制深刻地影響了庫中間的每一個
   組件。你可能疑惑:內存模式和算法或者容器類接口有什麼關係?如果你使用size_t這樣的東西,你
   就無法使用 T* 對象,因爲存在不同的指針類型(T*, T huge *, 等等)。這樣你就不能使用引用,因
   爲內存模式不同的話,會產成不同的引用類型。這樣就會導致標準庫產生龐大的分支。

   另外一件重要的事情是我們原先的關聯類型數據結構被擴展了。這比較容易一些,但是最爲標準的東
   西總是很困難的,因爲我們做的東西人們要使用很多年。從容器的觀點看,STL做了十分清楚的二分
   法設計。所有的容器類被分成兩種:順序的和關聯的,就好像常規的內存和按內容尋址的內存一般。
   這些容器的語義十分清楚。

   當我到滑鐵盧以後,Bjarne用了不少時間來安慰我不要太在意成敗與否,因爲雖然看上去似乎不會成功,
   但是我們畢竟做到了最好。我們試過了,所以應該坦然面對。成功的期望很低。我們估計大部分的意見
   將是反對。但是事實上,確實有一些反對意見,但不佔上風。滑鐵盧投票的結果讓人大跌眼鏡,80%贊
   成,20%反對。所有人都預期會有一場惡戰,一場大論戰。結果是確實有爭論,但投票是壓倒性的。

Q: STL對於1994年2月發行的ANSI/ISO C++工作文件中的類庫有何影響?
A: STL被放進了滑鐵盧會議的工作文件裏。STL文檔被分解成若干部分,放在了文件的不同部分中。Mike 
   Vilot負責此事。我並沒有過多地參與編輯工作,甚至也不是C++委員會的成員。不過每次有關STL的
   建議都由我來考慮。委員會考慮還是滿周到的。

Q: 委員會後來又做了一些有關模板機制的改動,哪些影響到了STL?
A: 在STL被接受之前,有兩個變化影響到了我們修訂STL。其一是模板類增加了包含模板函數的能力。STL
   廣泛地使用了這個特性來允許你建立各種容納容器的容器。一個單獨的構造函數就能讓你建立一個能容
   納list或其他容器的的vector。還有一個模板構造函數,從迭代子構造容器對象,你可以用一對迭代子
   當作參數傳給它,這對迭代子之間的元素都會被用來構造新的容器類對象。另一個STL用到的新特性是
   把模板自身當作模板參數傳給模板類。這項技術被用在剛剛提到的allocator中。

Q: 那麼STL影響了模板機制嗎?
A: 在弗基山谷的會議中,Bjarne建議給模板增加一個“局部特殊化”(partial specialization)的特性。
   這個特性可以讓很多算法和類效率更高,但也會帶來代碼體積上的問題。我跟Bjarne在這個建議上共同
   研究了一段時間,這個建議就是爲了使STL更高效而提出的。我們來解釋一下什麼是“局部特殊化”。
   你現在有一個模板函數 swap( T&, T& ),用來交換兩個參數。但是當T是某些特殊的類型參數時,你想
   做一些特殊的事情。例如對於swap( int&, int& ),你想用一種特別的操作來交換數據。這一點在沒有
   局部特殊化機制的情況下是不可能的。有了局部特殊化機制,你可以聲明一個模板函數如下:
   
       template <class T> void swap( vector<T>&, vector<T>& );

   這種形式給vector容器類的swap操作提供了一種特別的辦法。從性能的角度講,這是非常重要的。如果
   你用通用的形式去交換vector,會使用三個賦值操作,vector被複制三次,時間複雜度是線性的。然而,
   如果我們有一個局部特殊化的swap版本專門用來交換兩個vector,你可以得到一個時間複雜度爲常數的,
   非常快的操作,只要移動vector頭部的兩個指針就OK。這能讓vector上的sort算法運行得更快。沒有局
   部特殊化,讓某一種特殊的vector,例如vector<int>運行得更快的唯一辦法是讓程序員自己定一個特殊
   的swap函數,這行得通,但是加重了程序員的負擔。在大部分情況下,局部特殊化機制能夠讓算法在某
   些通用類上表現得更高效。你有最通用的swap,不那麼通用的swap,更不通用的swap,完全特殊的swap
   這麼一系列重載的swap,然後你使用局部特殊化,編譯器會自動找到最接近的那個swap。另一個例子是
   copy。現在我們的copy就是通過迭代子一個一個地拷貝。使用模板特殊化可以定義一個模板函數:

 template <class T> T** copy( T**, T**, T** );

   這可以用memcpy高效地拷貝一系列指針來實現,因爲是指針拷貝,我們可以不必擔心構造對象和析構
   對象的開銷。這個模板函數可以定義一次,然後供整個庫使用,而且用戶不必操心。我們使用局部特殊
   化處理了一些算法。這是個重要的改進,據我所知在弗基山谷會議上得到了好評,將來會成爲標準的一
   部分。(後來的確成了標準的一部分 —— 譯者)

Q: 除了標準類庫外,STL對那一類的應用程序來說最有用處?
A: 我希望STL能夠引導大家學習一種新的編程風格:通用編程。我相信這種風格適用於任何種類的應用程
   序。這種風格就是:用最通用的方式來寫算法和數據結構。這些結構所要求的語義特性應該能夠被清楚
   地歸類和分類,而這些歸類分類的原則應該是任何對象都能滿足的。理解和發展這種技術還要很長時間,
   STL不過是這個過程的起點。
 
   我們最終會對通用的組件有一個標準的分類,這些組件具有精心定義的接口和複雜度。程序員們將不必
   在微觀層次上編程。你再也不用去寫一個二分查找算法。就是在現在,STL也已經提供了好幾個通用的
   二分查找算法,凡是能用二分查找算法的場合,都可以使用這些算法。算法所要求的前提條件很少:你
   只要在代碼裏使用它。我希望所有的組件都能有這麼一天。我們會有一個標準的分類,人們不用再重複
   這些工作。

   這就是Douglas McIlroy的夢想,他在1969年關於“構件工廠”的那篇著名文章中所提出來的東西。STL
   就是這種“構件工廠”的一個範例。當然,還需要有主流的力量介入這種技術的發展之中,光靠研究機
   構不行,工業界應該想程序員提供組件和工具,幫助他們找到所需的組件,把組件粘合到一起,然後
   確定複雜度是否達到預期。

Q: STL沒有實現一個持久化(persistent)對象容器模型。map和multimap似乎是比較好的候選者,它們可以
   把對象按索引存入持久對象數據庫。您在此方向上做了什麼工作嗎,或者對這類實現有何評論?
A:很多人都注意到這個問題。STL沒實現持久化是有理由的。STL在當時已經是能被接受的最巨大的庫了。
   再大一點的話,我認爲委員會肯定不會接受。當然持久化是確實是一些人提出的問題。在設計STL,特別
   是設計allocator時,Bjarne認爲這個封裝了內存模式的組件可以用來封裝持久性內存模式。Bjarne的
   洞察秋毫非常的重要和有趣,好幾個對象數據庫公司正在盯着這項技術。1994年10月我參加了Object
   Database Management Group的一個會議,我做了一個關於演說。他們非常感興趣,想讓他們正在形成
   中的組件庫的接口與STL一致,但不包括allocator在內。不過該集團的某些成員仔細分析了allocator
   是否能夠被用來實現持久化。我希望與STL接口一致的組件對象持久化方案能在接下來的一年裏出現。

Q:set,multiset,map和multimap是用紅黑樹實現的,您試過用其他的結構,比如B*樹來實現嗎?
A:我不認爲B*適用於內存中的數據結構,不過當然這件事還是應該去做的。應該對許多其他的數據結構,
   比如跳錶(skip list)、伸展樹(splay tree)、半平衡樹(half-balanced tree)等,也實現STL容器的標
   準接口。應該做這樣的研究工作,因爲STL提供了一個很好的框架,可以用來比較這些結構的性能。結口
   是固定的,基本的複雜度是固定的,現在我們就可一個對各種數據結構進行很有意義的比較了。在數據
   結構領域裏有很多人用各種各樣的接口來實現不同的數據結構,我希望他們能用STL框架來把這些數據
   結構變成通用的。
   (譯者注:上面所提到的各種數據結構我以爲大多並非急需,而一個STL沒有提供而又是真正重要的數據
     結構是哈希結構。後來在Stepanov和Matt Austern等人的SGI*STL中增補了hashset,hashmap和
     hashtable三種容器,使得這個STL實現才比較完滿。衆所周知,紅黑樹的時間複雜度爲O(logN), 而理
     想hash結構爲O(1)。當然,如果實現了持久化,B+樹也是必須的。)

Q:有沒有編譯器廠商跟您一起工作來把STL集成到他們的產品中去?
A:是的,我接到了很多廠家的電話。Borland公司的Peter Becker出的力特別大。他幫助我實現了對應
   Borland編譯器的所有內存模式的allocator組件。Symantec打算爲他們的Macintosh編譯器提供一個STL
   實現。Edison設計集團也很有幫助。我們從大多數編譯器廠商都得到了幫助。
   (譯者注:以目前的STL版本來看,最出色的無疑是SGI*STL和IBM STL for AS/390,所有Windows下的
     的STL實現都不令人滿意。根據測試數據,Windows下最好的STL運行在PIII 500MHz上的速度遠遠
     落後與在250MHz SGI工作站(IRIX操作系統)上運行的SGI*STL。以我個人經驗,Linux也是運行STL
     的極佳平臺。而在Windows的STL實現中,又以Borland C++Builder的Rogue Wave STL爲最差,其效率
     甚至低於JIT執行方式下的Java2。Visual C++中的STL是著名大師P. J. Plauger的個人作品,性能較
     好,但其queue組件效率很差,慎用)

Q:STL包括了對MS-DOS的16位內存模式編譯器的支持,不過當前的重點顯然是在32位上線性內存模式
   (flat model)的操作系統和編譯器上。您覺得這種面向內存模式的方案以後還會有效嗎?
A:拋開Intel的體系結構不談,內存模式是一個對象,封裝了有關指針的信息:這個指針的整型尺寸和
   距離類型是什麼,相關的引用類型是什麼,等等。如果我們想利用各種內存,比如持久性內存,共享
   內存等等,抽象化的工作就非常重要了。STL的一個很漂亮的特性是整個庫中唯一與機器類型相關的
   部分——代表真實指針,真實引用的組件——被封裝到大約16行代碼裏,其他的一切,容器、算法等
   等,都與機器無關(真是牛啊!)。從移植的觀點看,所有及其相關的東西,象是地址記法,指針等
   等,都被封裝到一個微小的,很好理解的機制裏面。這樣一來,allocator對於STL而言就不是那麼
   重要了,至少不像對於基本數據結構和算法的分解那麼重要。


Q:ANSI/ISO C標準委員會認爲像內存模式這類問題是平臺相關的,沒有對此做出什麼具體規定。C++委員
   會會不會採取不同的態度?爲什麼?
A:我認爲STL在內存模式這一點上跟C++標準相比是超前的。但是在C和C++之間有着顯著的不同。C++有構造
   函數和new操作符來對付內存模式問題,而且它們是語言的一部分。現在看來似乎讓new操作符像STL容器
   使用allocater那樣來工作是很有意義的。不過現在對問題的重要性不像STL出現之前那麼顯著了,因爲
   在大多數場合,STL數據結構將讓new失業。大部分人不再需要分配一個數組,因爲STL在做這類事情上
   更爲高效。要知道我對效率的迷信是無以復加的,可我在我的代碼裏從不使用new,彙編代碼表明其效率
   比使用new時更高。隨着STL的廣泛使用,new會逐漸淡出江湖。而且STL永遠都會記住回收內存,因爲當
   一個容器,比如vector退出作用域時,它的析構函數被調用,會把容器裏的所有東西都析構。你也不必
   再擔心內存泄漏了。STL可以戲劇性地降低對於垃圾收集機制的需求。使用STL容器,你可以爲所欲爲,
   不用關心內存的管理,自有STL構造函數和析構函數來對付。


Q:C++標準庫子委員會正在制訂標準名空間(namespace)和異常處理機制。STL類會有名空間嗎,會拋出異
   常嗎?
A:是的。該委員會的幾個成員正在考慮這件事,他們的工作非常卓越。

Q:現在的STL跟最終作爲標準的STL會有多大不同?委員會會不會干預某些變化,新的設計會不會被嚴格地控
   制起來?
A:多數人的意見看起來是不希望對STL做任何重要的改變。

Q:在成爲標準之前,程序員們怎樣的一些STL經驗?
A:他們可以從butler.hpl.hp.com/stl當下STL頭文件,在Borland和IBM或其他足夠強勁的的編譯器中使用它。
   學習這種編程技術的唯一途徑是編程,看看範例,試着用這種技術來編程。

Q:您正在和P. J. Plauger合作一本STL的書。那本書的重點是什麼?什麼時候面世?
A:計劃95年夏天面世,重點是對STL實現技術的詳解,跟他那本標準C庫實現和標準C++庫實現的書類似。他是
   這本書的第一作者。該書可以作爲STL的參考手冊。我希望跟Bjarne合作另寫一本書,在C++/STL背景下介紹
   語言與庫的交互作用。

   好多工作都等着要做。爲了STL的成功,人們需要對這種編程技術進行更多的試驗性研究,更多的文章和書籍
   應該對此提供幫助。要準備開設此類課程,寫一些入門指南,開發一些工具幫助人們漫遊STL庫。STL是一個
   框架,應該有好的工具來幫助使用這個框架。
   (譯者注:他說這番話時,並沒有預計到在接下來的幾年裏會發生什麼。由於Internet的大爆炸和Java、
     VB、Delphi等語言的巨大成功,工業界的重心一下子從經典的軟件工程領域轉移到Internet上。再加上
     標準C++直到98年才制訂,完全符合要求的編譯器直到現在都還沒有出現,STL並沒有立刻成爲人們心中的
     關注焦點。他提到的那本書也遲遲不能問世,直到前幾天(2001年元旦之後),這本衆人久已期盼的書
     終於問世,由P. J. Plauger, Alexander Stepanov, Meng Lee, David Musser四大高手聯手奉獻,
     Prentice Hall出版。不過該書主要關注的是STL的實現技術,不適用於普通程序員。

     另外就P. J. Plauger做一個簡介:其人是標準C中stdio庫的早期實現者之一,91年的一本關於標準
     C庫的書使他名滿天下。他現在是C/C++ Use's Journal的主編,與Microsoft保持着良好的,甚至是
     過分親密的關係,Visual C++中的STL和其他的一些內容就是出自他的那隻生花妙筆。不過由於跟MS
     的關係已經影響到了他的中立形象,現在有不少人對他有意見。

     至於Stepanov想象中的那本與Stroustrup的書,起碼目前是沒聽說。其實這兩位都是典型的編程聖手,
     跟Ken Thompson和Dennis Ritchie是一路的,懶得親自寫書,往往做個第二作者。如果作爲第一作者,
     寫出來的書肯定是學院味十足,跟標準文件似的,不適合一般程序員閱讀。在計算機科學領域,編程
     聖手同時又是寫作高手的人是鳳毛麟角,最著名的可能是外星人D. E. Knuth, C++領域裏則首推前面
     提到的Andrew Koenig。可惜我們中國程序員無緣看到他的書。)

Q:通用編程跟OOP之間有什麼關係?
A:一句話,通用編程是OOP基本思想的自然延續。什麼是OOP的基本思想呢?把組件的實現和接口分開,並
   且讓組件具有多態性。不過,兩者還是有根本的不同。OOP強調在程序構造中語言要素的語法。你必須
   得繼承,使用類,使用對象,對象傳遞消息。GP不關心你繼承或是不繼承,它的開端是分析產品的分類,
   有些什麼種類,他們的行爲如何。就是說,兩件東西相等意味着什麼?怎樣正確地定義相等操作?不單
   單是相等操作那麼簡單,你往深處分析就會發現“相等”這個一般觀念意味着兩個對象部分,或者至少
   基本部分是相等的,據此我們就可以有一個通用的相等操作。再說對象的種類。假設存在一個順序序列
   和一組對於順序序列的操作。那麼這些操作的語義是什麼?從複雜度權衡的角度看,我們應該向用戶提
   供什麼樣的順序序列?該種序列上存在那些操作?那種排序是我們需要的?只有對這些組件的概念型分
   類搞清楚了,我們才能提到實現的問題:使用模板、繼承還是宏?使用什麼語言和技術?GP的基本觀點
   是把抽象的軟件組件和它們的行爲用標準的分類學分類,出發點就是要建造真實的、高效的和不取決於
   語言的算法和數據結構。當然最終的載體還是語言,沒有語言沒法編程。STL使用C++,你也可以用Ada
   來實現,用其他的語言來實現也行,結果會有所不同,但基本的東西是一樣的。到處都要用到二分查找
   和排序,而這就是人們正在做的。對於容器的語義,不同的語言會帶來輕微的不同。但是基本的區別很
   清楚是GP所依存的語義,以及語義分解。例如,我們決定需要一個組件swap,然後指出這個組件在不同的
   語言中如果工作。顯然重點是語義以及語義分類。而OOP所強調的(我認爲是過分強調的)是清楚的定義
   類之間的層次關係。OOP告訴了你如何建立層次關係,卻沒有告訴你這些關係的實質。
   (這段不太好理解,有一些術語可能要過一段時間纔會有合適的中文翻譯——譯者)

Q:您對STL和GP的未來怎麼看?
A:我剛纔提到過,程序員們的夢想是擁有一個標準的組件倉庫,其中的組件都具有良好的、易於理解的和標
   準的接口。爲了達成這一點,GP需要有一門專門的科學來作爲基礎和支柱。STL在某種程度上開始了這項
   工作,它對於某些基本的組件進行了語義上的分類。我們要在這上面下更多的功夫,目標是要將軟件工程
   從一種手工藝技術轉化爲工程學科。這需要一門對於基本概念的分類學,以及一些關於這些基本概念的定
   理,這些定理必須是容易理解和掌握的,每一個程序員即使不能很清楚的知道這些定理,也能正確地使用
   它。很多人根本不知道交換律,但只要上過學的人都知道2+5等於5+2。我希望所有的程序員都能學習一些
   基本的語義屬性和基本操作:賦值意味着什麼?相等意味着什麼?怎樣建立數據結構,等等。

   當前,C++是GP的最佳載體。我試過其他的語言,最後還是C++最理想地達成了抽象和高效的統一。但是
   我覺得可能設計出一種語言,基於C和很多C++的卓越思想,而又更適合於GP。它沒有C++的一些缺陷,特別
   是不會像C++一樣龐大。STL處理的東西是概念,什麼是迭代子,不是類,不是類型,是概念。說得更正式
   一些,這是Bourbaki所說的結構類型(structure type),是邏輯學家所說的理念(theory),或是類型
   理論學派的人所說的種類(sort),這種東西在C++裏沒有語言層面上的對應物(原文是incarnation,直譯
   爲肉身——譯者),但是可以有。你可以擁有一種語言,使用它你可以探討概念,精化概念,最終用一種
   非常“程序化”(programmatic,直譯爲節目的,在這裏是指符合程序員習慣的——譯者)的手段把它們
   轉化爲類。當然確實有一些語言能處理種類(sorts),但是當你想排序(sort)時它們沒什麼用處。我們
   能夠有一種語言,用它我們能定義叫做foward iterator(前向迭代子)的東西,在STL裏這是個概念,沒有
   C++對應物。然後我們可以從forword iterator中發展出bidirectional iterator(雙向迭代子),再發展
   出random iterator。可能設計一種語言大爲簡化GP,我完全相信該語言足夠高效,其機器模型與C/C++充分
   接近。我完全相信能夠設計出一種語言,一方面儘可能地靠近機器層面以達成絕對的高效,另一方面能夠處
   理非常抽象化的實體。我認爲該語言的抽象性能夠超過C++,同時又與底層的機器之間契合得天衣無縫。我認爲GP會影響到語言的研究方向,我們會有適於GP的實用語言。從這些話中你應該能猜出我下一步的計劃。

                                                                                       mengyan
             譯於2001年1月


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章