程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> More Effective C++之考慮變更程序庫

More Effective C++之考慮變更程序庫

編輯:關於C++

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

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

例如,考慮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 <stdio.h>
#else
#include <iostream>
#include <iomanip>
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) // 設置小數位置
   << setiosflags(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); 輸入方便。

但是操作符<<既是類型安全(type-safe)又可以擴展,而printf則不具有這兩種優點。

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

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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved