MoreEffectiveC++之考慮變更程序庫

字號:

程序庫的設(shè)計(jì)就是一個折衷的過程。理想的程序庫應(yīng)該是短小的、快速的、強(qiáng)大的、靈活的、可擴(kuò)展的、直觀的、普遍適用的、具有良好的支持、沒有使用約束、沒有錯誤的。這也是不存在的。為尺寸和速度而進(jìn)行優(yōu)化的程序庫一般不能被移植。具有大量功能的的程序庫不會具有直觀性。沒有錯誤的程序庫在使用范圍上會有限制。真實(shí)的世界里,你不能擁有每一件東西,總得有付出。
    不同的設(shè)計(jì)者給這些條件賦予了不同的優(yōu)先級。他們從而在設(shè)計(jì)中犧牲了不同的東西。因此一般兩個提供相同功能的程序庫卻有著完全不同的性能特征。
    例如,考慮iostream和stdio程序庫,對于C++程序員來說兩者都是可以使用的。iostream程序庫與C中的stdio相比有幾個優(yōu)點(diǎn)(參見Effective C++)。例如它是類型安全的(type-safe),它是可擴(kuò)展的。然而在效率方面,iostream程序庫總是不如stdio,因?yàn)閟tdio產(chǎn)生的執(zhí)行文件與iostream產(chǎn)生的執(zhí)行文件相比尺寸小而且執(zhí)行速度快。
    首先考慮執(zhí)行速度的問題。要想掌握iostream和stdio之間的性能差別,一種方法就是用這兩個程序庫來運(yùn)行benchmark程序。不過你必須記住benchmark也會撒謊。不僅很難拿出一組能夠代表程序或程序庫典型用法的數(shù)據(jù),而且就算拿出來也是沒用,除非有可靠的方法判斷出你或你的客戶的具有什么樣的特征。不過在解決一個問題的不用方法的比較上,benchmark還是能夠提供一些信息,所以盡管完全依靠benchmark是愚蠢的,但是忽略它們也是愚蠢的。
    讓我們測試一個簡單的benchmark程序,只測試最基本的I/O功能。這個程序從標(biāo)準(zhǔn)輸入讀取30000個浮點(diǎn)數(shù),然后把它們以固定的格式寫到標(biāo)準(zhǔn)輸出里。編譯時(shí)預(yù)處理符號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) // 設(shè)定field寬度
    << setprecision(5) // 設(shè)置小數(shù)位置
    << setiosflags(ios::showpoint) // keep trailing 0s
    << setiosflags(ios::fixed) // 使用這些設(shè)置
    << d;
    #endif
    if (n % 5 == 0) {
    #ifdef STDIO
     printf("\n");
    #else
     cout << '\n';
    #endif
    }
    }
    return 0;
    }