STL標準模板庫學習 STL 很好很強大

2021-06-14 16:16:48 字數 4398 閱讀 8457

從標準輸入裝置(一般是鍵盤)讀入一些整型資料,然後對它們進行 排序,最終將結果輸出到標準輸出裝置(一般是顯示器螢幕)。這是一種典型的處理方式,程式本身具備了乙個系統所應該具有的幾乎所有的基本特徵:輸入 + 處理 + 輸出。你將會看到兩個不同版本的程式。第乙個是沒有使用stl的普通c++程式,你將會看到完成這樣看似簡單的事情,需要花多大的力氣,而且還未必沒有一 點問題(真是吃力不討好)。第二個程式的主體部分使用了stl特性,此時在第乙個程式中所遇到的問題就基本可以解決了。同時,你會發現採用了stl之後, 程式變得簡潔明快,清晰易讀。 

有幾點是需要說明的:

這個例程的目的,在於向你演示如何在c++程式中使用stl,同時希望通 過實踐,證明stl所帶給你的確確實實的好處。程式中用到的一些stl基本元件,比如:vector(一種容器)、sort(一種排序演算法),你只需要有 乙個大致的概念就可以了,這並不影響閱讀**和理解程式的含義。

第一版:史前時代--轉木取火

在stl還沒有降生的"黑暗時代",c++程式設計師要完成前面所提到的那些功能,需要做很多事情(不過這比起c程式來,似乎好一點),程式大致是如下這個樣子的:

#include

#include

int compare(const void *arg1, const void *arg2);

void main(void)

// 比較兩個數的大小,

// 如果*(int *)arg1比*(int *)arg2小,則返回-1

// 如果*(int *)arg1比*(int *)arg2大,則返回1

// 如果*(int *)arg1等於*(int *)arg2,則返回0

int compare(const void *arg1, const void *arg2)

這是乙個和stl沒有絲毫關係的傳統風格的c++程式。因為程式的注 釋已經很詳盡了,所以不需要我再做更多的解釋。總的說來,這個程式看起來並不十分複雜(本來就沒有太多功能)。只是,那個compare函式,看起來有點費勁。指向它的函式指標被作為最後乙個實參傳入qsort函式,qsort是c程式庫stdlib.h中的乙個函式。以下是qsort的函式原型:

void qsort(void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

看起來有點令人作嘔,尤其是最後乙個引數。大概的意思是,第乙個引數 指明了要排序的陣列(比如:程式中的num),第二個引數給出了陣列的大小(qsort沒有足夠的智力預知你傳給它的陣列的實際大小),第三個引數給出了陣列中每個元素以位元組為單位的大小。最後那個長長的傢伙,給出了排序時比較元素的方式(還是因為qsort的智商問題)。

以下是某次執行的結果:

輸入:0 9 2 1 5

輸出:0 1 2 5 9

有乙個問題,這個程式並不像看起來那麼健壯(robust)。如果我們輸入的數字個數超過max_size所規定的上限,就會出現陣列越界問題。如果你在visual c++的ide環境下以控制台方式執行這個程式時,會彈出非法記憶體訪問的錯誤對話方塊。這個問題很嚴重,嚴重到足以使你開始重新審視這個程式的**。為了彌補程式中的這一缺陷。我們不得不考慮採用如下三種方案中的一種:

採用大容量的靜態陣列分配。

限定輸入的資料個數。

採用動態記憶體分配。

第一種方案比較簡單,你所做的只是將max_size改大一點,比 如:1000或者10000。但是,嚴格講這並不能最終解決問題,隱患仍然存在。假如有人足夠耐心,還是可以使你的這個經過糾正後的程式崩潰的。此外,分配乙個大陣列,通常是在浪費空間,因為大多數情況下,陣列中的一部分空間並沒有被利用。再來看看第二種方案,通過在第乙個for迴圈中加入乙個限定條件,可 以使問題得到解決。比如:for (int n = 0; cin >> num[n] && n < max_size; n ++); 但是這個方案同樣不甚理想,儘管不會使程式崩潰,但失去了靈活性,你無法輸入更多的數。 看來只有選擇第三種方案了。是的,你可以利用指標,以及動態記憶體分配 妥善的解決上述問題,並且使程式具有良好的靈活性。這需要用到new,delete操作符,或者古老的malloc(),realloc()和 free()函式。但是為此,你將犧牲程式的簡潔性,使程式**陡增,**的處理邏輯也不再像原先看起來那麼清晰了。乙個compare函式或許就已經令 你不耐煩了,更何況要實現這些複雜的處理機制呢?很難保證你不會在處理這個問題的時候出錯,很多程式的bug往往就是這樣產生的。同時,你還應該感謝 stdlib.h,它為你提供了qsort函式,否則,你還需要自己實現排序演算法。如果你用的是冒泡法排序,那效率就不會很理想。……,問題真是越來越讓 人頭疼了! 關於第乙個程式的討論就到此為止,如果你對第三種方案感興趣的話,可以嘗試著自己編寫乙個程式,作為思考題。這裡就不準備再浪費筆墨去實現這樣乙個讓人不甚愉快的程式了。

第二版:工業時代--元件化大生產

我們應該慶幸自己所生活的年代。工業時代,科技的發展所帶來的巨大便利已經影響到了我們生活中的每個細節。如果你還在以原始人類的方式生活著,那我真該懷疑你是否屬於某個生活在非洲或者南美叢林裡的原始部落中的一員了,難道是瑪雅文明又重現了? stl便是這個時代的產物,正如其他科技成果一樣,c++程式設計師也應該努力使自己適應並充分利用這個"高科技成果"。讓我們重新審視第一版的那個破爛不堪的程式。試著使用一下stl,看看效果如何。

#include

#include

#include

using namespace std;

void main(void)

這個程式的主要部分改用了stl的部件,看起來要比第乙個程式簡潔一 點,你已經找不到那個討厭的compare函式了。它真的能很好的執行嗎?你可以試試,因為程式的執行結果和前面的大致差不多,所以在此略去。我可以向你 保證,這個程式是足夠健壯的。不過,可能你還沒有完全看明白程式的**,所以我需要為你解釋一下。畢竟,這個戲法變得太快了,較之第乙個程式,一眨眼的功 夫,那些老的c++程式設計師所熟悉的**都不見了,取而代之的是一些新鮮玩意兒。程式的前三行是包含的標頭檔案,它們提供了程式所要用到的所有c++特 性(包括輸入輸出處理,stl中的容器和演算法)。不必在意那個.h,並不是我的疏忽,程式保證可以編譯通過,只要你的c++編譯器支援標準c++規範的相關部分。你只需要把它們看作是一些普通的c++標頭檔案就可以了。事實上,也正是如此,如果你對這個變化細節感興趣的化,可以留意一下你身旁的佐餐。同樣可以忽略第四行的存在。加入那個宣告只是為了表明程式引用到了std這個標準名字空間(namespace),因為stl中的那些玩意兒全都包含在那裡面。只有通過這行宣告,編譯器才能允許你使用那些有趣的特性。 程式中用到了vector,它是stl中的乙個標準容器,可以用來存放一些元素。你可以把vector理 解為int [?],乙個整型的陣列。之所以大小未知是因為,vector是乙個可以動態調整大小的容器,當容器已滿時,如果再放入元素則vector會悄悄擴大自己的容量。push_back是vector容器的乙個類屬成員函式,用來在容器尾端插入乙個元素。main函式中第乙個while迴圈做的事情就是不斷向 vector容器尾端插入整型資料,同時自動維護容器空間的大小。sort是stl中的標準演算法,用來對容器中的元素進行排序。它需要 兩個引數用來決定容器中哪個範圍內的元素可以用來排序。這裡用到了vector的另兩個類屬成員函式。begin()用以指向vector的首端,而end()則指向vector的末端。這裡有兩個問題,begin()和end()的返回值是什麼?這涉及到stl的另乙個重要部件--迭代器 (iterator),不過這裡並不需要對它做詳細了解。你只需要把它當作是乙個指標就可以了,乙個指向整型資料的指標。相應的sort函式宣告也可以看 作是void sort(int* first, int* last),儘管這實際上很不精確。另乙個問題是和end()函式有關,儘管前面說它的返回值指向vector的末端,但這種說法不能算正確。事實上,它 的返回值所指向的是vector中最末端元素的後面乙個位置,即所謂pass-the-end value。這聽起來有點費解,不過不必在意,這裡只是稍帶一提。總的來說,sort函式所做的事情是對那個準整型陣列中的元素進行排序,一如第乙個程式中的那個qsort,不過比起qsort來,sort似乎要簡單了許多。程式的最後是輸出部分,在這裡vector完全可以以假亂真了,它所提供的對元素的訪問方式簡直和普通的c++內建陣列一模一樣。那個size函式用來返回vector中的元素個數,就相當於第乙個程式中的變數n。這兩行**直觀的不用我再多解釋了。 我想我的耐心講解應該可以使你大致看懂上面的程式了,事實上stl的 運用使程式的邏輯更加清晰,使**更易於閱讀。試問,有誰會不明白begin、end、size這樣的字眼所表達的含義呢(除非他不懂英語)?試著執行一 下,看看效果。再試著多輸入幾個數,看看是否會發生陣列越界現象。實踐證明,程式執行良好。是的,由於vector容器自行維護了自身的大小,c++程式 員就不用操心動態記憶體分配了,指標的錯誤使用畢竟會帶來很多麻煩,同時程式也會變得冗長無比。這正是前面第三種方案的缺點所在。 再仔細審視一下你的第乙個stl版的c++程式,回顧一下第一章所提到的那些有關stl的優點:易於使用,具有工業強度……,再比較一下第一版的程式,我想你應該有所體會了吧!

學習標準模板庫STL

標準模板庫 stl,即standard template library 是乙個c 軟體庫。stl常見頭件包括algorithm,functional iterator vector list deque queue stack等。在學習過程中與其他常見庫對比,如mfc,wxwidgets,itk,...

STL 標準模板庫)

此篇只是乙個目錄,將分成單篇去完成 stl 主要有三個部分組成 容器,迭代器,演算法。順序容器 向量 vector 雙端佇列 dequeue 表 list ps copy 方法 關聯容器 集合 set 多重集合 multiset 對映 map 多重對映 multimap 容器介面卡 棧 stack ...

Stl(標準模板庫)

stl 標準模板庫 stl的目的是標準化元件,這樣就不用重新開發,可以使用現成的元件。我們常用到的stl容器有vector list deque map multimap set和multiset。1.簡單概括 如果需要高效的隨機訪問,不在乎插入和刪除的效率,使用vector 類似陣列 2 如果需要...