这是我在阅读Effective c++中认为比较重要的部分,下面给出了我对这一节的理解,并写出对应的比较容易理解的代码。
以下代码中重写的operator* 以传值方式返回。效率低,内部调用构造函数,返回时调用拷贝构造、析构函数。例如下面代码调用了3次构造函数 1次拷贝构造 4次析构。(VS2015 debug版)
class Rational {
public:
Rational(int numer = 0,int denom = 1):n(numer),d(denom){
cout << "ctor" << endl;
}
~Rational(){ cout << "destruct" << endl; }
Rational(const Rational& a) {
n = a.n;
d = a.d;
cout << "copy ctor" << endl;
}
public:
int n, d;
friend Rational operator*(const Rational&lhs, const Rational&rhs);
};
Rational operator*(const Rational&lhs,const Rational&rhs){
Rational res(lhs.n*rhs.d,lhs.n*rhs.n);
return res;
}
int main() {
Rational a(2,5);
Rational b(1,1);
Rational c = a*b;
return 0;
而返回引用时: 调用3次构造 3次析构,但返回的值未定义。
class Rational {
public:
Rational(int numer = 0,int denom = 1):n(numer),d(denom){
cout << "ctor" << endl;
}
~Rational(){ cout << "destruct" << endl; }
Rational(const Rational& a) {
n = a.n;
d = a.d;
cout << "copy ctor" << endl;
}
public:
int n, d;
string s = "abc";
friend Rational& operator*(const Rational&lhs, const Rational&rhs);
};
Rational &operator*(const Rational&lhs,const Rational&rhs){
Rational res(lhs.n*rhs.d,lhs.n*rhs.n);
return res;
}
int main() {
Rational a(2,5);
Rational b(1,1);
Rational &c = a*b;
cout << c.s << endl; //未定义的值
return 0;
}
而在函数内创建堆对象时,接收者确无法找到指向那块内存的指针而无法回收。
现在想进一步在返回引用的基础上再增大效率,希望再减少一个构造的成本,则改写operator*,在其内创建static对象,从而取消每一次的构造成本,但如果此时重写operator == ,则使用operator*的对象的比较每一次都是返回true,因为它们返回的都是引用,因此调用端看到的永远是static Rational对象的”现值”!; 代码如下:
class Rational {
public:
Rational(int numer = 0,int denom = 1):n(numer),d(denom){
cout << "ctor" << endl;
}
~Rational(){ cout << "destruct" << endl; }
Rational(const Rational& a) {
n = a.n;
d = a.d;
cout << "copy ctor" << endl;
}
public:
int n, d;
friend Rational& operator*(const Rational&lhs, const Rational&rhs);
};
Rational &operator*(const Rational&lhs,const Rational&rhs){
static Rational res;
res.d = lhs.d*lhs.n;
res.n = lhs.n*lhs.n;
return res;
}
bool operator==(const Rational&lhs, const Rational&rhs) {
if (lhs.d == rhs.d&&lhs.n == rhs.n) {
cout << "true" << endl;
return true;
}
else {
cout << "false" << endl;
return false;
}
}
int main() {
Rational a(2,5);
Rational b(1,1);
Rational c(3, 3);
Rational d(4, 4);
a*b == c*d;
return 0;
}
正确写法就是让那个函数返回一个对象:
Rational operator*(const Rational&lhs,const Rational&rhs){
return Rational(lhs.n*rhs.d, lhs.n*rhs.n);
}
请记住
绝对不要返回一个pointer或者reference指向一个local stack对象, 或者是一个reference指向一个heap allocated对象,或者返回一个local static对象而且又可能同时会用到这个local static对象。