More Effective C++ 條款23 (轉)

worldblog發表於2007-12-11
More Effective C++ 條款23 (轉)[@more@]

:namespace prefix = o ns = "urn:schemas--com::office" />

庫的設計就是一個折衷的過程。理想的程式庫應該是短小的、的、強大的、靈活的、可擴充套件的、直觀的、普遍適用的、具有良好的支援、沒有使用、沒有錯誤的。這也是不存在的。為尺寸和速度而進行的程式庫一般不能被移植。具有大量功能的的程式庫不會具有直觀性。沒有錯誤的程式庫在使用範圍上會有限制。真實的世界裡,你不能擁有每一件東西,總得有付出。

不同的設計者給這些條件賦予了不同的優先順序。他們從而在設計中犧牲了不同的東西。因此一般兩個提供相同功能的程式庫卻有著完全不同的特徵。

例如,考慮iostream和stdio程式庫,對於C++程式設計師來說兩者都是可以使用的。iostream程式庫與C中的stdio相比有幾個優點(參見Effective C++)。例如它是型別的(type-safe),它是可擴充套件的。然而在方面,iostream程式庫總是不如stdio,因為stdio產生的與iostream產生的執行檔案相比尺寸小而且執行速度快。

首先考慮執行速度的問題。要想掌握iostream和stdio之間的效能差別,一種方法就是用這兩個程式庫來執行benchmark程式。不過你必須記住benchmark也會撒謊。不僅很難拿出一組能夠代表程式或程式庫典型用法的資料,而且就算拿出來也是沒用,除非有可靠的方法判斷出你或你的客戶的具有什麼樣的特徵。不過在解決一個問題的不用方法的比較上,benchmark還是能夠提供一些資訊,所以儘管完全依靠benchmark是愚蠢的,但是忽略它們也是愚蠢的。

讓我們測試一個簡單的benchmark程式,只測試最基本的I/O功能。這個程式從標準輸入讀取30000個浮點數,然後把它們以固定的格式寫到標準輸出裡。編譯時預處理符號STDIO決定是使用stdio還是iostream。如果定義了這個符號,就是用stdio,否則就使用iostream程式庫。

#ifdef STDIO

#include

#else

#include

#include

using namespace std;

#endif

 

 

const int VALUES = 30000;  // # of values to read/write

 

int main()

{

  double d;

 

  for (int n = 1; n <= VALUES; ++n) {

#ifdef STDIO

  scanf("%lf", &d);

  printf("%10.5f", d);

#else

  cin >> d;

  cout  << setw(10)  // 設定field寬度

  << setprecision(5)  // 設定小數位置

  << setiolags(ios::showpoint)  // keep trailing 0s

  << setiosflags(ios::fixed)  // 使用這些設定

  << d;

#endif

 

  if (n % 5 == 0) {

#ifdef STDIO

  printf("n");

#else

  cout << 'n';

#endif

  }

  }

 

  return 0;

}

當把正整數的自然對數傳給這個程式,它會這樣輸出:

0.00000  0.69315  1.09861  1.38629  1.60944

1.79176  1.94591  2.07944  2.19722  2.30259

2.39790  2.48491  2.56495  2.63906  2.70805

2.77259  2.83321  2.89037  2.94444  2.99573

3.04452  3.09104  3.13549  3.17805  3.21888

這種輸出至少表明了使用iostreams也能這種也能產生fixed-format I/O。當然,

cout  << setw(10)

  << setprecision(5)

  << setiosflags(ios::showpoint)

  << setiosflags(ios::fixed)

  << d;

遠不如  printf("%10.5f", d); 輸入方便。

但是運算子<

我做了幾種、操作和的不同組合,在其上執行這個程式,在每一種情況下都是使用stdio的程式執行得較快。優勢它僅僅快一些(大約20%),有時則快很多(接近200%),但是我從來沒有遇到過一種iostream的實現和與其相對應的stdio的實現執行速度一樣快。另外,使用stdio的程式的尺寸比與相應的使用iostream的程式要小(有時是小得多)。(對於程式現實中的尺寸,這點差異就微不足道了)。

應該注意到stdio的高效性主要是由其程式碼實現決定的,所以我已經測試過的系統其將來的實現或者我沒有測試過的系統的當前實現都可能表現出iostream和stdio並沒有顯著的差異。事實上,有理由相信會發現一種iostream的程式碼實現比stdio要快,因為iostream在編譯時確定它們運算元的型別,而stdio的則是在執行時去解析格式字串(format string)。iostream和stdio之間效能的對比不過是一個例子,這並不重要,重要的是具有相同功能的不同的程式庫在效能上採取不同的權衡措施,所以一旦你找到的瓶頸(透過進行 profile 參見條款16),你應該知道是否可能透過替換程式庫來消除瓶頸。比如如果你的程式有I/O瓶頸,你可以考慮用stdio替代iostream,如果程式在動態分配和釋放上使用了大量時間,你可以想想是否有其他的operator newoperator delete的實現可用(參見條款8和Effective C++條款10)。因為不同的程式庫在效率、可擴充套件性、移植性、型別安全和其他一些領域上蘊含著不同的設計理念,透過變換使用給予效能更多考慮的程式庫,你有時可以大幅度地提高軟體的效率。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991366/,如需轉載,請註明出處,否則將追究法律責任。

相關文章