標籤:

在取消同步的情況下,為什麼cin的速度比scanf快?

測試了一下 讀入0-9 999 999這1000w個整數,scanf用了3.1秒,cin用了2.6秒。

這是為什麼?

沒有開優化和其他奇怪的東西,gcc 版本4.9.2


C++的iostream很多時候本來就比C性能好,快一點不奇怪,只是默認跟C同步導致很多人誤以為iostream比C慢。iostream在編譯的時候,數據類型就確定了,數據和文本的轉換很直接。而scanf/printf這些,%d%f這些都是要運行期動態判斷的。用iostream的時候,想要性能的話,注意利用緩存,比如cout不要隨便endl,不需要保證立即輸出的話用"
"替代。

iostream雖然不少人不喜歡,但是比C的複雜那麼多不是沒有意義的。所謂「簡單高效」絕大多數情況下都是美好的意淫,高效的系統往往需要複雜的實現。

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

有人要求說說「高效的系統往往需要複雜的實現」:

邏輯上,這個答案很簡單:如果簡單就能高效,我們還要那麼多複雜的系統幹嘛?

簡單舉幾個例子,排序裡面選擇排序邏輯和實現最簡單直接,速度卻往往墊底,快的一般還得快排堆排;最早的cpu簡單,沒有浮點處理器,後來有了x87,再後來有了矢量單元,每一次複雜化都帶來大提速;串列程序最簡單最容易維護,但是數據量大或者計算量大了,你必須並行化來提高效率;同步io簡單,但是為了高效你得非同步;絕大多數的緩存都不是邏輯上必須的,沒有它功能一樣能實現,但是為了高效你必須使用緩存……

非it系統裡面,生物從簡單到複雜進化也是為了高效率,提高生存能力,魚、爬行動物、哺乳動物的心臟結構越來越複雜,一個主要動力就是減少靜脈血和動脈血的混合,提高輸氧效率;古代政府簡單,但是大多數事情上效率肯定比不上複雜的現代政府(古代皇帝拍板杜絕扯皮的除外,但是那樣錯誤決定可能性更大,返工也是一種低效);天天噓寒問暖追妹子簡單,但是為了加快進度和成功率你得多管齊下使出複雜的十八般武藝~( ̄▽ ̄~)~


一種可能是scanf的模式是運行期生成的,cin在編譯期就能完成決議


兄弟,這樣不貼代碼是掰扯不明白這類事情的。

如果你的測試非常簡單,就是這樣的比較。

cin&>&>var;

scanf("%d",var);

這樣的測試。

那麼原因很簡單,因為scanf多了一步,解析你的格式化描述字元串而已。要不你增加一些格式控制再試驗一下?或者一次導入的數據再多一點。

二如果要去討論C++ iostream 和C 的早年幾個API的性能差別,如果只討論標準實現,基本上還是C++的 iostream略遜一籌。

為什麼呢?我原來的判斷在於過多次的的函數調用。但後來發現可能主要還是在於iostream 的機制和實現。iostream 的優勢在於類型安全,但在格式化的實現上,反而複雜了很多個維度(這些維度也讓他多了不少函數調用)。而且還極其不好用。遠沒有printf一類函數的格式化處理字元串清爽簡單,

其實按照現有的編輯器,和C++ 11的標準中新增的模板變參功能,實現一個類似printf的類型安全函數不難,有一些標稱速度完滅printf和iostream的IO庫也就都是類似的原理,一看編譯器生成對應的函數。當然這有個問題是編譯膨脹的問題,但我沒在大項目用個這個方案。不敢判斷有多少膨脹,對編譯速度有多少影響。但我的測試(有格式化參數控制),即使是對比printf,確實可以快過10%。

BTW:什麼是取消同步?


推薦閱讀:

GCC編譯的程序為什麼沒有正確調用拷貝構造函數?
C++ 程序員有必要熟練使用除標準庫以外的第三方庫嗎?
為什麼c++的整數會溢出,而Python的整數不會溢出呢?
為什麼scanf()用cmd編譯可以通過,但用vs2015卻不能通過?

TAG:C | CC |