22.该返回对象时则返回对象

pass-by-reference固然很好,但是实际应用时可能会发生一些很尴尬的场景,比如reference指向并不存在的对象。
具体而言,就是你试图用一个reference去绑定一个局部变量(local对象),这直接引发了雪崩。

可能你会在函数内部定义一个static对象,并用一个reference去绑定它,最终返回一个指向static对象的reference。在多线程下这种操作极易导致安全问题,并且它还有更致命的错误。举例而言:

1
2
3
4
5
6
const Rational& operator*(const Rational& lhs,
const Rational& rhs){
static Rational res;
res = ...;//乘法操作
return res;
}

当我们试图去使用operator时:
1
2
3
4
5
6
7
Rational a,b,c,d;
if(a*b)==(c*d){
...
}
else{
...
}

事实上if判定永远是true,因为​reference是static对象的别名,而那个对象和自己比对必然是相等的(虽然两次operator
的确各自改变了它的值,但最终仅返回了最终修改后的对象的reference)

固执的人可能会试图去使用static array.. 这比使用static对象还要令人发指。首先无法判定array的大小,小了不够用,多了又浪费。而且n太大了还会造成效率低下(执行了n次构造与析构)。这个愚蠢的想法无法优化,就算把array换成vector也不会改善情况

因此,不如就坦然地返回一个新对象,值得注意的是这里可以配合返回值优化使构造与析构的成本降到最低:(返回值优化详见 More Effective C++ 20)

1
2
3
inline const Rational operator*(const Rational& lhs,const Rational& rhs){
return Rational(...);//返回值优化
}