与C++语言密切相关的效率问题
了解临时对象的来源
临时对象意味着对象的构造以及析构,我们必须了解临时对象的产生,以规避一些效率问题,临时对象主要的两个产生方式:
1.隐式类型转换被施行以求函数调用成功。
2 函数返回对象的时候。
对于第一种情况:
以下代码解释:
size_t countChar(const string& str,char ch);
char buffer[100]="Hello world!";
countChar(buffer,'h');
当buffer被传递给countChar的时候,临时对象就以buffer为参数产生了临时对象。这里值得注意的是临时对象只可能在by value参数传递方式以及by reference to const 参数传递方式管用。
如果上面的例子是countChar(string & str,char ch)那么我们的参数调用就不会产生临时对象,因为这里我们可能更改原来的数据,但是其实如果我们产生了临时对象的话,我们只改了副本。
对于第二种情况:
const Number Operator+(const Number& lhs,const Number &rhs);这个函数就会产生临时对象用于返回,就便要付出构造以及析构的成本。这里需要了解编译器的返回值优化RVO(return value optimization);
像上述例子,返回一个对象的优化做法是在函数外产生对象,并将其引用传递到其中。
举个例子就是:
Rational a=10;
Rational b(1,2);
Rational c=a*b;
如果operator*写为:
const Rational operator*(const Rational&lhs ,const Ratinal &rhs)
{
//这样这个临时对象就可以被优化掉了
return result(lhs.numerator()*rhs.numerator(),lhs.denominator(),rhs.denominator());
}
利用重载技术来避免隐式类型转换
以一个例子来解释上述问题:
class UPInt
{
public:
UPInt();
UPInt(int value);
}
const UPInt operator+(const UPInt& lhs,const UPInt &rhs)
{
...
}
这个函数在我们这样使用的时候就不那么合理了:
UPInt upi1,upi2;
UPInt upi3=upi1+10;
UPInt upi3=10+upi2;
显然10会通过单变量构造函数转换成UPInt而产生临时对象,我们考虑如果UPInt是特别大的对象,这样的做法是欠妥的,我们可以利用重载来消除隐式转换:
const UPInt operator+(const UPInt& lhs,int rhs)
{
}
const UPInt operator+(int,const UPInt &rhs)
{
}
当然重载的时候我们也要牢记80-20法则,对于不太影响效率的那80%的代码,我们可能就不必会他进行这种优化了。
考虑以操作符复合形式取代其独身形式
首先作为程序的设计者我们需要同时提供两种形式的操作符,但是我们知道需要知道复合形式的操作肯定是比独身形式的效率高的。一般的实现方式是利用其复合形式来实现其独身形式
templae <class T>
const T operator+(const T&lhs,const T&rhs )
{
return T(lhs)+=rhs;
}
这种形式由于匿名对象的产生也会导致编译器的RVO优化。
这一节其实我们强调的是复合形式的操作符由于不产生临时对象,所以效率会更高一点。
考虑使用其他程序库
不同的程序库将效率 扩充性 移植性 类型安全性等做了不同的设计具体化。有时候我们可以尝试找找看是否存在一个功能相似的程序库而其在效率上有较高的权重。如果有,那么有改用他(但是也要给予我们的80 20法则)
举个例子就是:
如果你的程序有一个I/O瓶颈,就可以考虑以stdio取代iostreams 但如果你的程序话费了许多时间在动态内存分配和释放方面,或许就应该看看是否有其他提供了operator new 和operator delete的程序库产品。
了解虚函数 多重继承 虚基类 执行期类型决定(RTTI)的成本
虚函数让对象内存变大,并且以为着虚函数不能被inline 多重继承以及虚基类将带来对象的进一步变大。RTTI:只有当某种类型用于至少一个虚函数时,才保证我们能够检测独享的动态类型(因为虚标的实现) 注意对象的类型信息存储在type_info对象中,利用typeid操作符可以取得某个class的type_info.
看到这些,可能你会逃回C阵营,但是你用c所实现的虚函数机制,可能跟C++实现的机制性能相差特别远。