為什麼 C 語言的輸入輸出函數比 C++ 的輸入輸出流要快?

平時做ACM賽題時,即使選用C++語言,選手們一般也用scanf讀入大規模數據,因為實際經驗得出用C語言的輸入輸出函數比C++的輸入輸出流更快,這是為什麼?


如果是用了ios::sync_with_stdio(false)的話是可以達到近似scanf的速度的。

一下該函數簡單的介紹。

速度慢的主要原因是同步標準輸入輸出。

static void sync_with_stdio();

Synchronizes the C++ streams with the standard I/O system. The first time this function is called, it resets the predefined streams (cin, cout, cerr, clog) to use astdiobuf object rather than a filebuf object. After that, you can mix I/O using these streams with I/O using stdin, stdout, and stderr. Expect some performance decrease because there is buffering both in the stream class and in the standard I/O file system.

After the call to sync_with_stdio, the ios::stdio bit is set for all affected predefined stream objects, and cout is set to unit buffered mode.


----這似乎是一個深坑,給人挖出來了-----

這類測試,總是有人做過的。探尋C++最快的讀取文件的方案,這個文章,測試的很清楚了。

不過他沒有測試MAC機器的。

我提供一組數據

mac 10.9,XCODE5.1.1

輸入,100萬個隨機數,文件大小10.5M。

scanf測試

./scan_in_test &<./scan_data.txt

Cost time: 139 ms

./cin_test &<./scan_data.txt (使用sync_with_stdio(false))

Cost time: 3436 ms

./cin_test &<./scan_data.txt (不使用sync_with_stdio(false))

Cost time: 3449 ms

測試的結果是,MAC下面的XCode,用不用sync_with_stdio(false),沒有什麼區別。

懶得點擊上面的鏈接的,直接看下面附上鏈接文章中的的一些測試結果數據(測試1000萬數據)

各個平台有差異,還是實測下,最保險。


C++ 的 iostream 是 version2.0 綜合症的集中體現


跟compiler implement os kernel有關的東西有什麼好討論的

附上icpc 2014 final 給的環境 你自己組一個環境benchmark一下,誰快就用誰

  • OS:
    • Ubuntu 12.04.3 LTS Linux (64-bit)
  • Languages:
    • C/C++
    • GCC 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
  • Compilation of Submissions
    • C gcc -g -O2 -std=gnu99 -static $* -lm
    • C++ g++ -g -O2 -std=gnu++0x -static $*

順便一提 雖然我不做ICPC 但都-std=gun++0x了 stl才是現在情況下acmer的首選

參考資料

Programming Environment

https://gcc.gnu.org/gcc-4.6/cxx0x_status.html

·······························分割線··································

順便一吐說printf是調用os api ,cout是頭文件的。。。


這個問題我以前研究過。

首先說因為iostream和stdio的同步問題導致了iostream會變慢,可以通過ios::sync_with_stdio(false)手動關閉這個同步,可能有加速作用

-------------------------以下基本上是HDU和POJ的經驗,其他OJ暫時不明

根據我曾經大約100多題的測試,ios::sync_with_stdio(false)只對C++ 有用,G++基本上無用,而且很多時候如果用了ios::sync_with_stdio(false)再加上cout和printf的混用,輸出順序會有不同。

-------------------

所以一般的建議是scanf最好,printf可以格式化,對acm要求按照格式輸出來說最方便。

PS:現場賽教練會議的時候有時候會說iostream的事情


原因上面的大大們都說完了,我再補充幾個小點。

1. sync_with_stdio(false),有可能會導致RE(在a+b problem裡面)。具體原因不詳,問題貌似還不能復現。所以一直不敢用這個。

2. cout的輸出格式比較麻煩,還是用printf來的比較爽。

3. cout 有個小坑,例如:

cout &<&< 123456.7 &<&< endl;

輸出結果:

正式比賽中萬一手一抖寫出這樣的代碼真的會被自己坑的欲哭無淚。


cin &>&> 需要進行自動檢測類型,內部執行的代碼很長。


這就好比兩個函數,其中一個為了適應外界各種差異,碼了100行,還有一個函數只處理了一種情況,碼了5行,然後有人開始比較這兩個函數的快慢,我想說這有意義嗎?


就是快。。。不要信樓上的sync_with_stdio, 有時它照樣會另你的程序超時。。。

至於原因,我覺得是因為scanf, printf是直接調用OS的API, 而cin/cout是頭文件中的代碼實現。

對了,有人可能發現fin/fout比fscanf/fprintf快。我個人覺得是因為default buffer大小不一樣。


endl會flush..這個在那本user guide就說過...


推薦閱讀:

TAG:C編程語言 | C | CC | ACM競賽 |