Don’t try to return a reference when you must return an object.
必须返回对象时,别妄想返回其reference。
考虑如下代码
class Rational
{
private:
/* data */
int n, d; // 分子,分母
friend const Rational operator* (const Rational& lhs, const Rational& rhs);
public:
Rational(int numerator = 0, int denominator = 1);
~Rational();
};
Rational::Rational(int numerator, int denominator): n(numerator), d(denominator) {}
Rational::~Rational() {}
如何实现其乘法的运算符重载?
- 在stack空间创建对象,返回其引用
const Rational& operator* (const Rational& lhs, const Rational& rhs) // stack上创建对象,返回其reference
{
Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
return result;
}
reference指向了某个local对象,而local对象在函数退出之前被销毁了。(返回指针,指向某个local对象也是一样)
- 在heap空间创建对象,返回其引用
const Rational& operator* (const Rational& lhs, const Rational& rhs) // heap上创建对象,返回其reference
{
Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
return *result;
}
谁该对着你new
出来的对象实施delete
?
- 使用static对象,返回其引用
const Rational& operator* (const Rational& lhs, const Rational& rhs) // static对象,返回其reference
{
static Rational result;
result.assign(lhs.n * rhs.n, lhs.d * rhs.d);
return result;
}
问题1. 线程安全隐患
问题2. 考虑到如下代码
bool operator== (const Rational& lhs, const Rational& rhs)
{
return lhs.n * rhs.d == lhs.d * rhs.n;
}
bool flag = ((a * b) == (c * d));
cout << flag << endl; // flag恒为true
static对象永远是”最新“值。
总结
- 绝不要返回pointer或者reference指向一个local stack对象
- 或者reference指向一个heap-allocated对象
- 或者返回pointer或reference指向一个local static对象而可能需要多个这样的对象