2009-01-15 139 views

回答

25

std::ostringstream不是要求要慢一些,但實施時一般比較慢。 FastFormat's website has some benchmarks

流的標準庫設計支持遠遠超過snprintf。該設計旨在具有可擴展性,並且包含由公開公開方法調用的方法。這允許你從一個流類派生出來,並保證如果你超載了protect ed方法,你將得到你想要的行爲。我相信編譯器可以避免virtual函數調用的開銷,但我不知道有任何編譯器。

此外,流操作通常在內部使用可增長的緩衝區;這意味着相對較慢的內存分配。

+0

哇 - 我有一段時間沒去過馬修威爾遜的網站 - 看起來他過去幾個月都很忙... – 2009-01-15 01:52:18

+0

FastFormat測試是有偏見的。下載代碼後,您會看到snprintf()基準測試會調用一個名爲fastformat_util_snprintf()的函數,該函數包含一些可能會拋出測試的包裝代碼。但是你是對的,內存管理可能是ostringstream變慢的原因。 – Max 2009-01-16 11:13:26

+0

感謝您查看代碼。我只看過漂亮的圖表。 – 2009-01-20 09:10:05

0

這很有可能是因爲sprintf是用匯編編寫的CRT的一部分。 ostringstream是STL的一部分,可能更通用一些,並且有OOP代碼/開銷來處理。

+3

我非常強烈地懷疑有人在彙編中實現了`sprintf`,除了可能作爲一個練習受虐狂。一直回到UNIX V6,C運行時庫本身已經被編寫成C語言(除了一些很少用C語言編寫的東西,比如`setjmp`)。 – zwol 2012-09-19 15:42:09

3

絕對這是特定於實現的。

但是,如果你真的想知道,寫兩個小程序,並比較它們。您需要包含您想要的典型用法,這兩個程序需要生成相同的字符串,然後使用分析器查看時序信息。

然後你就會知道。

0

我知道printf家族函數比相應的C++函數(cout,cin和其他流)快的原因之一是後者進行類型檢查。由於這通常涉及一些重載操作員的請求,因此可能需要一些時間。實際上,在編程競賽中,爲了這個原因,通常建議您使用printf等而不是cout/cin。

8

有些人可能會告訴你,函數不能比彼此更快,但他們的實現可以。這是對的,我想我會同意。

除了基準以外,您不可能注意到其中的差異。 C++流一般趨於的原因是它們更加靈活。靈活性通常是以時間或代碼增長爲代價的。

在這種情況下,C++流基於流緩衝區。流本身就是保持格式化和錯誤標誌的地方,並調用C++標準庫的正確i/o構面(例如,用於打印數字的num_put),將值格式化良好的值打印到基礎流中連接到C++流的緩衝區。

所有這些機制 - 方面和緩衝區都是通過虛函數實現的。雖然確實沒有標記請注意,這些函數必須被實現爲比cStdio掛件慢,這實際上會使它們比通常使用c stdio函數稍慢(我基準了一段時間之前用gcc/libstdC++和事實上注意到一個放緩 - 但你幾乎沒有注意到在日常使用)。

1

有一個問題可能是由ostringstream增加的類型安全帶來額外的開銷。不過,我還沒有做過任何測量。

8

我們用sprintf(使用靜態分配的緩衝區)替換了內部循環中的一些stringstream,這在msvc和gcc中都有很大的不同。我想,這個代碼的動態內存管理:

 
{ 
    char buf[100]; 
    int i = 100; 
    sprintf(buf, "%d", i); 
    // do something with buf 
} 

 
{ 
    std::stringstream ss; 
    int i = 100; 
    ss << i; 
    std::string s = ss.str(); 
    // do something with s 
} 

簡單多了,但我很高興與stringstreams的整體性能。

0

作爲litb said,標準流支持許多我們並不總是需要的東西。 有些流實現擺脫了這個從未使用的靈活性,例如參見FAStream

0

是的,如果你用Visual C++ 5.0在幾百萬個數字上運行下面的函數,第一個版本的時間大約是第二個版本的兩倍,併產生相同的輸出。

將緊密循環編譯爲.exe文件並運行Windows時,「我是如何調查大多數性能好奇心的。 (`timethis'可在網上找到)

void Hex32Bit(unsigned int n, string &result) 
{ 
#if 0 
    stringstream ss; 
    ss 
     << hex 
     << setfill('0') 
     << "0x" << setw(8) << n 
    ; 
    result = ss.str(); 
#else 
    const size_t len = 11; 
    char temp[len]; 
    _snprintf(temp, len, "0x%08x", n); 
    temp[len - 1] = '\0'; 
    result = temp; 
#endif 
} 
相關問題