大的方面
- .单线程改多线程
- 同步改异步
- 动态库改静态库
小的方面
- 尽量减少值传递,多用引用来传递参数。
至于其中的原因,相信大家也很清楚,如果参数是int等语言自定义的类型可能能性能的影响还不是很大,但是如果参数是一个类的对象,那么其效率问题就不言而喻了。例如一个判断两个字符串是否相等的函数,其声明如下
bool Compare(string s1, string s2)
bool Compare(string *s1, string *s2)
bool Compare(string &s1, string &s2)
bool Compare(const string &s1, const string &s2)
其中若使用第一个函数(值传递),则在参数传递和函数返回时,需要调用string的构造函数和析构函数两次(即共多调用了四个函数),而其他的三个函数(指针传递和引用传递)则不需要调用这四个函数。因为指针和引用都不会创建新的对象。如果一个构造一个对象和析构一个对象的开销是庞大的,这就是会效率造成一定的影响。
- ++i和i++引申出的效率问题
从后加的实现方式可以知道,对象利用自己创建一个临时对象(自己在函数调用的一个复制),然后改变自己的状态,并返回这个临时对象,而前加的实现方式时,直接改变自己的内部状态,并返回自己的引用。第一点的论述可以知道后加实现时会调用复制构造函数,在函数返回时还要调用析构函数,而由于前加实现方式直接改变对象的内部状态,并返回自己的引用,至始至终也没有创建新的对象,所以也就不会调用构造函数和析构函数。
- 将小粒度函数声明为内联函数(inline)
调用函数是需要保护现场,为局部变量分配内存,函数结束后还要恢复现场等开销,而内联函数则是把它的代码直接写到调用函数处,所以不需要这些开销,但会使程序的源代码长度变大。所以若是小粒度的函数,如下面的Max函数,由于不需要调用普通函数的开销,所以可以提高程序的效率。
int Max(int a, int b)
{
return a>b?a:b;
}
- 初始化列表和构造函数赋值
初始化列表直接是在数据成员声明的时候就进行了初始化,因此它只执行了一次copy constructor。
首先,在构造函数执行前会通过default constructor创建数据成员,然后在构造函数中通过operator =进行赋值。因此它就比初始化列表多进行了一次函数调用。性能差异就出来了。