对于速度特别是资源使用方面代码效率的关注总是值得的,这篇文章提供给Symbian开发者一些应该熟知的方法。
栈使用
--------------------------------------------------------
应用程序每个线程标准的栈空间为8KB,应该被小心使用,因此:
1.除基本类型外,避免值拷贝
2.在堆而不是栈上创建大的对象或数组
3.用恰当的限制范围来将自动变量的生命周期减到最小
最后一点用下面的例子说明:
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();
内容可能是
void FunctionOne()
{
FunctionOne(0);
}
指针和引用
------------------------------------------------------------------
使用引用作为函数形参比指针更有效率。这是因为编译器必须在所有转换中保留空指针的值。
想象一个Cxxx类,派生自MYyy,如下:
class CXxx : public CBase , public MYyy {...};
那么,传递CXxx对象到接受Myyy为形参的函数时,编译器必须将sizeof(CBase)加到指针中,除非指针为NULL。
如果cp是一个CXxx*,且Func()是接受 Myyy*的函数,那么调用Func(cp)时将发生:
Func(MYyy* aM)(cp == NULL ? NULL :(TUint8*)cp+sizeof(CBase)));
空引用是不可能的,所以对它检查NULL没有必要。在ARM上,将CXxx*转换为MYyy*需要8个指令,而CXxx&到Myyy&的转换
只要两个。
浮点算术
-----------------------------------------------------------
浮点算术那是相当的慢,所以值得找一找有没有只用整数的替代算法。
比如,给你两个 TInt,aTop和aBottom,替代下面的算法:
TReal a = (TReal)aTop;
TReal b =(TReal) aBottom;
TReal c = a/b + 0.5;
TReal result;
Math::Round(result,c,0);
你应该使用
return ((2*aTop+aBottom)/(2*aBottom));
内联函数
-----------------------------------------------------------------
内联函数可以避免函数调用开销从而提高代码效率,它将操作伪装成函数以保持模块化。
但是,在使用它之前你应该检查:
1.代码紧凑性:内存资源受限意味着,比起大量的内联带代码,函数的调用开销更能接受。
2.二进制兼容性:改变内联函数的实现将破坏二进制兼容性。这在你的代码被其他Symbian开发者使用时很重要。
内联函数被接收的最一般情况是:
1.一两个机器字长的getter和setter函数,例如:
inline ConEnv const{return iConEnv;};
2.T类的微型构造函数:
inline TPoint::TPoint(TInt aX, TInt aY) {iX = aX, iY = aY;};
3.在瘦模板惯用法中:参见Thin template
4.某些其他的操作和函数,可能是模板,其定义在一个操作映射到另一个操作时不受改变,例如:
template<class T> inline T Min(T aLeft, T aRight)
{return (aLeft < aRight ? aLeft : aRight);}
当删除对象时不做空指针检查
-----------------------------------------------------
C++规定了delete 0不做任何事,所以你不必像这样写代码
if(iX)
delete iX;