翻譯自SDK » Developer Library » Symbian OS Guide » Essential idioms » Code efficiency
概要
速度和資源使用方面的代碼效率總是值得關注的,本節提出的方法對Symbian平台的開發人員來說是很常用的。
棧應用
應用程式中的每個線程都有一個8Kb的標準棧,應當小心地使用。因此:
Ø 除了基本類型避免值拷貝。
Ø 應該在堆上而不是棧上建立任何大的對象或數組。
Ø 通過適當的域最小化自動變數的生命週期。
最後一點可以通過下面的例子說明:
void ABadFunction()
{
TBigObject Object1;
TBigObject Object2;
TBigObject Object3;
GetTwoObjectValues(Object1,Object2);
Object3=SumObjects(Object1,Object2);
FunctionWithUnknownStackOverhead(Object3);
}
上面的代碼中,對象Object1和Object2一直佔用棧並貫穿到FunctionWithUnknownStackOverhead()的生命週期中,即使那時已不需要使用它們。它們應當在調用發生之前從棧上刪除。可以用下面的方法實現:
void ABetterFunction()
{
TBigObject Object1;
GetTotalObjectValues(Object1);
FunctionWithUnknownStackOverhead(Object1);
}
void GetTotalObjectValues(TBigObject &aObject)
{
TBigObject Object1;
TBigObject Object2;
GetTwoObjectValues(Object1,Object2);
aObject=SumObjects(Object1,Object2);
}
通過把代碼分離到兩個函數中,你可以確保棧的使用符合需求。
函數重載
如果一個函數有預設參數並經常以預設值進行調用,應當考慮提供一個沒有參數的重載函數。這是因為每次提供預設參數會使編譯器在函數被調用的地方產生額外的代碼。
例如有下面的函數:
void FunctionOne(TInt aInt=0);
在代碼中經常以下面形式調用:
FunctionOne();
這時應考慮提供一個下面這樣的函數:
void FunctionOne()
{
FunctionOne(0);
}
指標和引用
使用引用做為函數參數比指標更有效率。這是因為編譯器不得不維護null 指標通過所有的轉換。
假設一個類CXxx從混合類Myyy派生:
class CXxx : public CBase,public MYyy {...};
在傳遞一個CXxx指標到參數為Myyy指標的函數時,編譯器不得不把把指標加上sizeof(CBase),除非這個指標為空白。例如cp是一個CXxx指標並且Func()的參數為Myyy指標,在執行Func(cp)調用時就會像下面這樣:
Func((MYyy* aM)(cp==NULL ? NULL : (TUint8*)cp+sizeof(CBase)));
因為引用不可為空,所以在使用時不用判斷它是否為空白。在ARM處理器上,CXxx*轉換到MYyy*需要8條指令,但是CXxx&轉換到MYyy&只需要2條指令。
浮點數運算
浮點數運算效率很低,因此有必要找出一種只使用整數運算的演算法。
例如下面的例子,aTop和aBottom是Tint類型:
TReal a = (TReal)aTop;
TReal b = (TReal)aBottom;
TReal c = a/b;
TReal result;
Math::Round(result,c,0);
return (TInt)result;
可以換成下面效率更好的代碼:
return((2*aTop+aBottom)/(2*aBottom));
內嵌函式
內嵌函式通過消除函數調用來提高代碼的速度,並且保持它的模組化特徵。然而在使用它之前需要確定兩個問題:
Ø 代碼簡潔性:有限的儲存資源意味著函數調用的開銷要比使用很大的內嵌函式更好。
Ø 二進位相容性:更改內嵌函式的實現會破壞程式的二進位相容性。如果代碼要被其他開發人員使用這點是很重要的。
內嵌函式通常在下面的情況中使用:
Ø 取得和設定一到兩個機器字的值,例如:
inline ConEnv() const { return iConEnv; };
Ø T類的簡單建構函式:
inline TPoint::TPoint(TInt aX, TInt aY) { iX=aX; iY=aY; };
Ø 在瘦模板中的用法:參考:SDK» Developer Library » Symbian OS Guide » Essential idioms » Thin templates
Ø 那些映射其它運算的函數,並且確定其中的運算子,函數或模板的定義不輕意改變,例如:
template <class T> inline T Min(T aLeft,T aRight)
{ return(aLeft<aRight ? aLeft : aRight); }
刪除指標時不用做是否為空白的判斷
C++規定delete 0不做任何事,因此從不需要寫下面類似的代碼:
if (iX)
delete iX;