我们知道一个返回对象的函数很难有很高的效率,因为传值会调用对象内的构造函数和析构函数;而一些函数必须要返回对象,这是难以避免的,所以,我们关心的重点,并不是去消除返回对象,而是怎么减少返回对象所用的开销上来;
幸好,编译器支持返回值优化,能让编译器消除临时对象的开销;下面我们考虑简单实现一个有理数的代码:
#include <iostream>
#include<opencv2\core\core.hpp>
using namespace std;
using namespace cv;
class Rational
{
public:
Rational(int x,int y):a(x),b(y){
cout<<"构造函数"<<endl;
};
~Rational(){
cout<<"析构函数"<<endl;
};
Rational(const Rational& rhs){
this->a=rhs.a;
this->b=rhs.b;
cout<<"复制构造函数"<<endl;
}
int ReturnA()const{return a;}
int ReturnB()const{return b;}
inline const Rational operator*(const Rational& rhs){
Rational temp(this->ReturnA()*rhs.ReturnA(),this->ReturnB()*rhs.ReturnB());
return temp;
}
friend ostream& operator<<( ostream& os,const Rational& s){
os<<s.a<<"/"<<s.b;
return os;
}
private:
int a;
int b;
};
int main() {
Rational obj1(2, 3), obj2(4,6);
double dur;
dur=static_cast<double>(getTickCount());
Rational obj3 = obj1 * obj2;
dur=static_cast<double>(getTickCount())-dur;
dur=dur/getTickFrequency();
cout<<"obj3= "<<obj3<<endl;
cout<<"花费的时间:"<<dur<<endl;
cout<<endl;
return 0;
}
上述代码的结果是:
构造函数
构造函数
构造函数
复制构造函数
析构函数
obj3= 8/18
花费的时间:0.00292201
析构函数
析构函数
析构函数
请按任意键继续. . .
再看下经过以下返回值优化的代码:
inline const Rational operator*(const Rational& rhs){
return Rational(this->ReturnA()*rhs.ReturnA(),this->ReturnB()*rhs.ReturnB());
}
其结果是:
构造函数
构造函数
构造函数
obj3= 8/18
花费的时间:0.000826902
析构函数
析构函数
析构函数
请按任意键继续. . .
从以上结果对比中,很清楚的看到做返回值优化用的时间少很多,仅仅只需要为obj3 = obj1 * obj2,花费一个构造函数,因为obj3是一个新变量,这是无法避免的,而其他开销几乎没有;
牢记:返回值优化(RVO)
**inline const Rational operator*(const Rational& rhs){
return Rational(this->ReturnA()*rhs.ReturnA(),this->ReturnB()*rhs.ReturnB());**
}
这里内联函数可有可无,注意:这种优化对普通的赋值运算符无效;最终结论是,在保持语意正确的前提下,没有更好的优化了
参考:More Effective C++ (侯捷译)