effective c++条款21:必须返回对象时,别忘想返回其reference

版权声明:转载请注明出处,谢谢!!! https://blog.csdn.net/qhdhnbd110/article/details/83586088

        在条款20,我们讨论了pass-by-value与pass-by-reference-to-const的传参效率问题,结果是对于自定义类型,pass-by-reference-to-const方式往往更加高效,那么我们就会想到,如果返回值也利用pass-by-reference-to-const方式返回,那会不会更好一点呢?

        考虑下面Rational类实现了两个有理数的乘积:

#include<iostream>
using namespace std;
class Rational
{
public:
	Rational(int n = 0, int d = 1)
	{
		this->n = n;
		this->d = d;
	}
	~Rational(){}
private:
	int n, d;   //n为分子,d为分母
public:
	friend const Rational operator*(const Rational &lhs, const Rational &rhs);
};
inline const Rational operator*(const Rational &lhs, const Rational &rhs)
{
	return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
}
int main()
{
	Rational a(1, 2);
	Rational b(4, 7);
	Rational c = a * b;
    return 0;
}

1. 修改为返回一个reference

inline const Rational &operator*(const Rational &lhs, const Rational &rhs)
{
    Rational Result(lhs.n * rhs.n, lhs.d * rhs.d);
	return Result;
}

如果我们返回了一个引用,那么它肯定是一个对象的别名,这个对象就是Result,但是注意,这个对象是一个局部变量,定义在栈帧中,也就是说,函数结束后,其会被自动销毁,那么返回的引用意味着代表了一块被释放的区域,这会引发一系列的无法预测的情况。

2. 修改为返回一个在堆中申请的对象

inline const Rational &operator*(const Rational &lhs, const Rational &rhs)
{
    Rational Result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
	return *Result;
}

这样我们就避免了局部变量销毁后带来的麻烦,但是考虑:

Rational a(1, 2);
Rational b(3, 4);
Rational c(5, 6);
Rational d = a * b * c;

这种情况下,b * c的返回值是一个堆中对象,那么我们就没有办法得到这个对象的指针,也就无法将其销毁,造成资源泄漏。

3. 修改为返回一个静态变量的引用

inline const Rational &operator*(const Rational &lhs, const Rational &rhs)
{
    static Rational Result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
	return *Result;
}

首先不考虑在多线程情况下的安全性,考虑用户合理的代码:

Rational a(1, 2);
Rational b(3, 4);
Rational c(5, 6);
Rational d(7, 8);
if((a * b) == (c * d))
    //...

你会发现a,b,c,d是什么值,if中的判断永远都是true。

将if中的语句改为等价的函数调用形式:

if(operator == (operator *(a, b), operator *(c, d)))

虽然两个operator*操作都各自修改了Result的值,但是在operator==调用时,两者的返回值都是同一个位置的引用,所以两者永远是相等的。

结论:当你需要在返回一个reference和一个object之间做出选择时,只需选择行为正确的那个就好,优化就交给编译器就好。

猜你喜欢

转载自blog.csdn.net/qhdhnbd110/article/details/83586088