条款21:必须返回对象时,别妄想返回其reference

知道了pass -by-value(传值)的效率牵连层面,从此一直适用pass-by-reference,就会犯下一个致命错误:开始传递一些reference指向其实并不存在的对象;考虑如下代码:

class Rational {
	public:
		Rational(int numberator = 0, int denominator = 1);
		//...
	private:
		int n, d;
		friend const Rational operator* (const Rational& lhs, const Rational &rhs);		
};

此版本的operator *以by value方式返回其计算结果(有构造和析构成本),如果返回其reference,就不需要付出该代价,如果要返回reference,就代表该对象已经存在了(一定是某物的另一个名称,指向某个既有的Rational对象);
函数创建新对象有两种途径:在stack空间或在heap空间创建;

// 在stack空间创建
const Rational& operator* (const Rational& lhs, const Rational& rhs) {
	Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
	return result;
}

上述函数问题是返回一个reference指向result,但是result是个local对象,而local对象在函数退出前被销毁了

// 在heap空间创建
const Rational& operator* (const Rational& lhs, const Rational& rhs) {
	Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
	return *result;
}
Rational w, x, y, z;
w = x * y * z;

上述函数还是必须付出一个"构造函数调用"代价,但是又出现了另外一个问题,谁该对着被你new出来的对象(result)实施delete?(无法解决,因为没有合理的办法让他们取得operator *返回的references背后隐藏的那个指针).

无论是on-the-stack还是on-the-top,都因为对operator *返回结果调用构造函数而收到惩罚;或许你又想到了"让operator *返回的reference指向一个被定义于函数内部的static Rational对象"

const Rational& operator* (const Rational& lhs, const Rational& rhs) {
	static Rational result;
	result = ...;
	return result;
}

像所有用上static对象的设计一样,会造成对多线程安全性的疑虑,还有如下问题,考虑代码

bool operator==(const Rational& lhs, const Rational& rhs);
Rational a, b, c, d;
if ((a * b) == (c * d)) {
	// 乘积相等时...
} else {
	// 乘积不相等时...
}

上述代码永远是相等的,因为每个reference指向operator *内部定义的static Rational对象,(两次operator *调用的确各自改变了static Rational对象值,但是由于它们返回的都是reference,因此调用端看到的永远是static Rational对象的"现值" )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值