在运行效率方面,由于C++的精心设计,C++程序其实并不比C程序低多少。导致C++效率低的一个重要原因是临时对象的滥用,因为对象在创建和释放时需要调用构造函数和析构函数,在一个大的类里这个开销很可观,因而需要灵活使用各种机制,减少临时对象的产生,从而提高程序效率。以下以一个Leader类来说明:
1. 类的构造函数、赋值函数(使用引用,减少临时对象的产生)
class Leader
{
string name;
int no;
double salary;
public:
Leader(){}
Leader(int o,string n):no(o),name(n){} //赋值列表可避免调用成员属性的默认构造函数
Leader(const Leader& l):no(l.no),name(l.name),salary(l.salary){}//拷贝构造函数,使用引用传参
Leader& operator=(const Leader& l)//赋值操作符重载
{
this->name = l.name;
this->no = l.no;
this->salary = l.salary;
return *this;
}
};
如果这么复制一个对象:
Leader l;//调用默认构造函数
l = m;//m也是一个Leader对象,调用赋值操作符函数
那不如这么写,这样更高效:
Leader l(m); //只调用一次拷贝构造函数
当然,不只是类的成员函数,非成员函数也可使用引用传参来减少临时对象的构造。
效率不高的做法 高效率做法
void print(Leader l) void print(const Leader& l)
{ {
//函数体 //函数体
} }
2. 只要有可能就推迟变量定义。在C中要将所有的局部变量定义在函数体头部,考虑到C++中对象创建的开销,这不是一个好习惯。如下例,如果大部分情况下b为"真",则拖延ld的定义可以大大提高函数的效率。
效率不高的做法 高效率做法
void Function( bool b ) void Function( bool b )
{ {
Leader ld; if(b)
if( b) {
{ // do something without xx
// do something without xx return;
return; }
} Leader ld;
//对ld进行操作 //对ld进行操作
} }
3. 那么对于循环会如何呢?如果一个变量仅仅在一个循环内使用,是循环外面定义它并在每次循环迭代时赋值给它更好一些,还是在循环内部定义这个变量更好一些呢?也就是说,下面这两个大致的结构中哪个更好一些?
// Approach A: define outside loop // Approach B: define inside loop
Leader l;
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
l = some value dependent on i; Leader l(some value dependent on i);
... ...
} }
下面是这两个方法的成本:
方法 A:1 个构造函数 + 1 个析构函数 + n 个赋值。
方法 B:n 个构造函数 + n 个析构函数。
对于那些赋值的成本低于一个构造函数/析构函数对的成本的类,方法 A 通常更高效。特别是在n变得很大的情况下。否则,方法 B 可能更好一些。此外,方法 A 与方法 B 相比,使得名字 l 在一个较大的区域(包含循环的那个区域)内均可见,这可能会破坏程序的易理解性和可维护性。因此得出以下结论:除非确信以下两点:
(1)赋值比构造函数/析构函数对成本更低
(2)你正在涉及你的代码中的性能敏感的部分
否则,应该默认使用方法 B。