第 2 個程式 (七)

來源:互聯網
上載者:User
// name:example2_3.cpp// alias:aesthetic version#include <iostream>#include <vector>#include <algorithm>#include <iterator>using namespace std;void main(void){typedef vector<int>int_vector;typedef istream_iterator<int>istream_itr;typedef ostream_iterator<int>ostream_itr;typedef back_insert_iterator< int_vector >back_ins_itr;// STL中的vector容器int_vector num;// 從標準輸入裝置讀入整數, // 直到輸入的是非整型資料為止copy(istream_itr(cin), istream_itr(), back_ins_itr(num));// STL中的排序演算法sort(num.begin(), num.end());// 將排序結果輸出到標準輸出裝置copy(num.begin(), num.end(), ostream_itr(cout, "/n"));}     

在這個程式裡幾乎每行代碼都是和STL有關的(除了main和那對花括弧,當然還有注釋),並且它包含了STL中幾乎所有的各大組件(容器container,迭代器iterator, 演算法algorithm, 適配器adaptor),唯一的遺憾是少了函數對象(functor)的身影。

還記得開頭提到的一個典型系統所具有的基本特徵嗎?--輸入+處理+輸出。所有這些功能,在上面的程式裡,僅僅是通過三行語句來實現的,其中每一行語句對應一種操作。對於資料的操作被高度的抽象化了,而演算法和容器之間的組合,就像搭積木一樣輕鬆自如,系統的耦合度被降到了極低點。這就是閃耀著泛型之光的STL的偉大力量。如此簡潔,如此巧妙,如此神奇!就像魔術一般,以至於再一次讓你摸不著頭腦。怎麼實現的?為什麼在看第二版程式的時候如此清晰的你,又墜入了五裡霧中(竊喜)。

請留意此處的標題(唯美主義的傑作),在實際環境中,你未必要做到這樣完美。畢竟美好願望的破滅,在生活中時常會發生。過於理想化,並不是一件好事,至少我是這麼認為的。正如前面提到的,這個程式只是為了展示STL的獨特魅力,你不得不為它的出色表現所折服,也許只有深諳STL之道的人才會想出這樣的玩意兒來。如果你只是一般性的使用STL,做到第二版這樣的程度也就可以了。

實在是因為這個程式太過"簡單",以至於我無法肯定,在你還沒有完全掌握STL之前,通過我的講解,是否能夠領會這區區三行代碼,我將盡我的最大努力。

前面提到的迭代器可以對容器內的任意元素進行定位和訪問。在STL裡,這種特性被加以推廣了。一個cin代表了來自輸入裝置的一段資料流,從概念上講它對資料流的訪問功能類似於一般意義上的迭代器,但是C++中的cin在很多地方操作起來並不像是一個迭代器,原因就在於其介面和迭代器的介面不一致(比如:不能對cin進行++運算,也不能對之進行取值運算--即*運算)。  為瞭解決這個矛盾,就需要引入適配器的概念。istream_iterator便是一個適配器,它將cin進行封裝,使之看起來像是一個普通的迭代器,這樣我們就可以將之作為實參傳給一些演算法了(比如這裡的copy演算法)。因為演算法只認得迭代器,而不會接受cin。對於上面程式中的第一個copy函數而言,其第一個參數展開後的形式是:istream_iterator(cin),其第二個參數展開後的形式是:istream_iterator()(如果你對typedef的文法不清楚,可以參考有關的c++語言書籍)。其效果是產生兩個迭代器的臨時對象,前一個指向整型輸入資料流的開始,後一個則指向"pass-the-end value"。這個函數的作用就是將整型輸入資料流從頭至尾逐一"拷貝"到vector這個准整型數組裡,第一個迭代器從開始位置每次累進,最後到達第二個迭代器所指向的位置。或許你要問,如果那個copy函數的行為真如我所說的那樣,為什麼不寫成如下這個樣子呢?

copy(istream_iterator<int>(cin), istream_iterator<int>(), num.begin()); 

你確實可以這麼做,但是有一個小小的麻煩。還記得第一版程式裡的那個數組越界問題嗎?如果你這麼寫的話,就會遇到類似的麻煩。原因在於copy函數在"拷貝"資料的時候,如果輸入的資料個數超過了vector容器的範圍時,資料將會拷貝到容器的外面。此時,容器不會自動成長容量,因為這隻是簡單地拷貝,並不是從末端插入。為瞭解決這個問題,另一個適配器back_insert_iterator登場了,它的作用就是引導copy演算法每次在容器末端插入一個資料。程式中的那個back_ins_itr(num)展開後就是:back_insert_iterator(num),其效果是產生一個這樣的迭待器對象。

終於將講完了三分之一(真不容易!),好在第二句和前一版程式沒有差別,這裡就略過了。至於第三句,ostream_itr(cout, "/n")展開後的形式是:ostream_iterator(cout, "/n"),其效果是產生一個處理輸出資料流的迭待器對象,其位置指向資料流的起始處,並且以"/n"作為分割符。第二個copy函數將會從頭至尾將vector中的內容"拷貝"到輸出裝置,第一個參數所代表的迭代器將會從開始位置每次累進,最後到達第二個參數所代表的迭代器所指向的位置。

這就是全部的內容。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.