相同的時間複雜度下,為什麼 C# 運行速度 比 C++ 快?

(1)感謝諸位的解答,今天我在VS下,選擇「開始執行(不調試)」,並且選擇「release」,最後在10秒內跑完。。。(雖然不知道選擇這種執行方式對不對)

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

(2)最近做到一道題目,發現調用std::string::operator+()和string.substr()很多次後,直接導致TLE,但是相同思路換種實現方式,就可以了。。這個也應該是我所提的問題C++比C#慢一些的原因之一。

今天忽然想起以前提的這個問題,當時不是很理解一些回答,現在恍然大悟,謝謝。。。。

------ 2015.12.02

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

課設是要求做有關中文文字處理的,我用的C++寫的,而另一個同學用的C#寫的,

核心演算法一樣,時間複雜度也相同,但是我的C++代碼需要跑幾分鐘,而另外一個同學幾秒鐘就跑完了。

請問一下,這是為什麼啊?

(我一直以為,C++主要用於寫底層的代碼,相同的時間複雜度下,應該很快,為什麼現在不如C#了呢?求解。。。)

代碼請見:Ubuntu Pastebin


不要用debug版和人家release版比性能。

我見過很多新手是不知道還有release版的,另外分不清run和debug run的也大有人在。

VC++的debug run下,程序結束時是要檢測內存泄漏和溢出的,這個過程非常慢,如果你有大量分配內存,那麼這個過程有幾分鐘都不奇怪。

C#就沒這個問題。


這麼離譜的差距我想是語言本身問題的可能性不大。


估計用了不當的方法寫C++。例如做了大量std::string::operator+()。但可能性太多,無代碼無法判斷。


有什麼好猜的,Profiling啊,多簡單的事情。


答題者看到你的描述一般是不會相信的,除非你把代碼貼出來詳細討論一下。


大哥你是不是把編譯時間算在裡面了?


我正想藉此表達下我的一個觀點(雖然v大也回答了這個問題)。

語言本質在於翻譯(的程度),所以理論上速度是C#&<=C++。

但有一個條件就是翻譯的質量(也就是是實現者的能力)。

那麼完全可能C#&>=C++。


一聽「文字處理」就知道為什麼了,話說std::string不是像你那樣用的。


三個字,上代碼


看下空間的複雜度,在是受限的內存下GC一次要人命。


如果說C#比C++性能高的地方的話,其實不多,很容易就能猜出來。譬如說你的演算法依賴於大量的new小對象,這種時候C#肯定要比C++快很多倍。


題主確定你倆的演算法是一樣的?


talk is cheap show me the code


題主,送你一句話:「以你代碼實現的質量之低,還輪不到拼演算法的時間複雜度的地步」。

- - - - -

首先向題主 @Jming S 道歉,自己圖一時口快沒有好好回答問題。

雖然自己沒有多少時間,但是我會把這個問題回答完。留原答案以作警示。

看了一下代碼,有很多地方可能會出現性能損失,但是由於用的電腦不是自己的,上面也沒法安裝編譯器,我也沒有測試用的數據,所以還請題主對每個函數分別測時,再對症下藥。

- - - - -

以下是我對每個函數的分析,側重於 STL 的使用。

InitText

如果我們用類似流程圖的東西來表示數據的拷貝/處理過程的話,應該是這樣:

ifstream → ostringstream → string →(for 循環)→ string

你的目的是遍歷整個文件,並進行 decoding,但是為什麼要做兩次多餘的拷貝呢?

我看到你的注釋里已經提到了,說明你已經懂得這個概念了,為什麼不好好利用呢?

所有基於 basic_istream 的類都有兩個非常好用的函數:std::basic_istream::peek 和 std::basic_istream::get (點擊以查看用法)。有了這兩個函數,你可以一個循環就搞定。

getOneWord, getTwoWord, getThreeWord

這三個函數大致相同,就放在一塊分析。

string →(for 循環中 substr)→ unordered_map → vector → 文件

  1. 開銷比較大的操作就在 substr 函數上,因為對於每個詞,都會創建一個 string 對象。因為你要存儲的詞都不超過 3 個字元,所以不妨用一個結構體來存儲詞。這樣就避免了 substr 的開銷。

  2. 另外一個需要考慮的地方是,如果你需要排序,並且數據量並不算很大,可以嘗試用 map 代替 unordered_map,因為 map 是排序的,所以可以直接遍歷迭代器輸出。
  3. 三個函數可以合併成一個函數,共用一個 vector 以避免重複申請內存的開銷。

最後還有一點想說的,如果必須用 C++ 實現的話並且有時間的話,可以考慮用 c-style string 把整個程序重寫一遍,不過這樣會更麻煩;如果沒有特殊要求的話,用腳本語言實現也可以,速度也不一定慢。


所謂c#跑的比c++快,拋去代碼本身的原因,在某些情況下:

c#發布的是中間代碼,CLI虛擬機會在第一次執行時編譯成最適用當前cpu型號的彙編指令。

而c++是直接按程序員的設置,編譯成彙編指令,二進位方式發布。

這就好比,c++是大工廠通用製品,c#會按照用戶情況自動定製。

然而,至於定製後是否真的能快,快了多少,很多時候是難說的。

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

不過問主的困惑,不用懷疑,肯定是代碼寫的太爛。。。


理論上C++是可以做到比C#快的,畢竟少一層,但是只能快一點點。

可是為了把程序寫成性能相當,付出的努力C#要低很多很多。

上代碼吧,讓大家參考參考。


別用奔4和人家i7比。


其實我想弱弱說一句,這還得看電腦配置……


少年……演算法差不多,時間差這麼多,不是你自己代碼寫錯了的話,你考慮下是不是拷貝構造函數調用太多了………


粗看了一下題主的代碼,建議注意臨時對象…


推薦閱讀:

在C++編程實踐中,我們是否應該放棄使用realloc這個函數?
初二學生能不能學C++?
visual studio為什麼把很多posix函數標記為deprecated?
長期用 C++ 和 MATLAB 做機器學習的你,有沒有遇到一個讓你相見恨晚的語言或包?

TAG:編程語言 | 編程 | C# | CC |