c++應用程式效能優化筆記(四)——建構函式效能
2010-05-18 20:39
容易成為效能瓶頸的c++語言特性
對程式的效能問題,根本原因並非採用什麼語言編寫程式。如果程式的框架設計不作修改,單純地把乙個c++程式用c或者彙編改寫,也不能保證總體效能會有提高。因此,正確的思路應該是:首先檢查和反思程式的總體框架,然後用效能檢測工具對實際執行進行準確測量,找出關鍵路徑和瓶頸所在,然後針對瓶頸進行分析和優化。
一些容易成為程式瓶頸的c++語言特性或操作如下:
缺頁。缺頁往往意味著需要外部儲存,因此需要盡量避免
從堆中動態申請和釋放記憶體。要盡可能優先考慮從執行緒棧中獲得記憶體,因為堆比棧慢許多,而且堆一般不可能都在物理記憶體中,從堆中生成的物件,指標在棧上,本身卻在堆中,即使相鄰生成的兩個物件,記憶體位置上也可能相隔很遠。因此用指標引用這些物件時,很可能會造成缺頁。而當前棧幀空間所在記憶體頁肯定在物理記憶體中,對棧中的變數訪問則不會引起缺頁。
複雜物件的建立和銷毀。物件建立只需要一條語句,卻可能是乙個深層次的遞迴呼叫。另外,臨時物件也是要高度警惕的。
函式呼叫。函式呼叫有固定的額外開銷,呼叫頻繁時,容易造成不必要的開銷。巨集和內聯函式都是為了消除這些固定額外開銷。提倡使用內聯函式,巨集不便開發者進行開發和除錯。
建構函式和析構函式效能分析
建立乙個物件,首先需取得所需的記憶體,然後在該記憶體上執行建構函式。
建立物件時,如果從執行緒執行棧中建立(區域性物件,語句類似object obj;),則在程式進入其作用域時,該物件的記憶體已經分配好了(一般都是通過移動棧指標),object obj;一句只需呼叫建構函式,且這種建立方式不需要程式顯式地呼叫析構函式,在程式執行到該物件作用域的終點時會自動呼叫析構函式,將空間返回給執行緒棧。
如果從全域性堆中建立物件,即通過new、malloc建立,物件的指標是乙個區域性物件,需要從執行緒棧中分配,而物件本身的記憶體是從全域性堆中分配的,需要顯式呼叫delete或free來銷毀。用delete或free來銷毀物件時,會呼叫其析構函式,並將所佔的全域性堆記憶體空間返回。但從銷毀物件到程式退出該作用域,物件的指標還存在於棧中,並指向物件本來的位置。顯然,這種情況下呼叫指標是非常危險的。win32平台下訪問這種指標,結果有三種可能情況:訪問違例、取得無意義值、取得其他物件。第一種會導致程序崩潰,後兩種雖然不會立即崩潰,但是可能會有不可**的行為操作或造成物件不必要的變化,需要謹慎避免。
建構函式構造物件時分兩個步驟:初始化和執行建構函式的函式體。需要注意幾點:
--建構函式是乙個遞迴操作,即先父類後子類,父類還有父類就先構造最上面的父類。每乙個在構造時都有嚴格的順序,即按成員變數在類中的宣告順序進行初始化。故在初始化列表中成員的宣告前後實際是無意義的。盡量養成使初始化列表與成員宣告順序一致的習慣,而且還要避免用某個成員變數的值初始化另外乙個成員變數。
--千萬不要以為只有初始化列表裡列出來的成員變數才在執行建構函式體之前進行初始化的。事實上,即使沒有在初始化列表中出現,所有成員變數仍然是在初始化這一步驟(也就是在執行建構函式的函式體前)完成初始化的。所以,我們常常在建構函式的函式體內對變數進行初始化,實際是非常浪費和降低效率的。應該養成用初始化列表進行賦初值的習慣。書中有個程式,就是通過多次迴圈來檢驗在建構函式的函式體內部進行初始化對效能的影響,在迴圈足夠大的情況下,這種方法耗時是非常顯著的。
--常量和引用型成員變數必須要在初始化列表中進行初始化。以前學c++也學過這點,但是知其然不知其所以然。現在明白了,因為這兩類一旦被賦值,整個生命週期內都不能修改,而在執行建構函式的函式體前,所有成員變數已經被初始化了,所以不能在建構函式體內對其賦值。
--大型複雜系統中,如果需要生成的物件屬於乙個複雜繼承體系的末端類,則其構造會引起一長串遞迴構造,會成為消耗cpu操作的主要部分。
避免臨時變數
c/c++語言的函式呼叫都是「值傳遞」的,也就是說,在呼叫函式時,實際生成了乙個引數的副本,在函式體內部所有修改都是針對這個副本的,因此這些修改在函式結束後會全部丟失。因此,最好使用引用傳遞引數(如果不需要修改,可傳入常量引用引數),避免不必要的構造和析構操作降低效率。
C 語言特性效能分析
c 語言特性效能分析 c 語言特性引起效能方面的問題主要有 1 缺頁 涉及記憶體分配 2 從堆中動態申請和釋放記憶體 3 複雜物件的建立和銷毀 4 函式呼叫開銷 動態例子 object obj new object delete obj 繼續使用 指標obj是乙個區域性變數,在棧中分配。delete...
C 容易忽略的特性
1 cin 標準輸入流物件,與標準輸入裝置相聯絡 通常指鍵盤 例如 cin 變數名 為提取運算子 輸入運算子 表示從鍵盤讀取資料放入變數中。2 cout 標準輸出流 流物件 與標準輸出裝置相聯絡 通常指顯示器 例如 cout 資料 為插入運算子 輸出運算子 表示將 資料 寫到顯示器上。3 cerr ...
C 語言特性中的效能分析
這是一本關於c 效能優化的書,比較不錯,叫 c 應用程式效能優化 第2版 c 語言特性中的效能分析 大多數開發人員通常都有這個觀點,即組合語言和c語言適合用來編寫對效能要求非常高的程式。而c 語言的主要應用範圍是編寫複雜度非常高,但是對 效能要求不是那麼嚴格的程式。因為在大多數人看來,c 語言相對前...