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

Don't try to return a reference when you must return an object.

使用 pass-by-reference 会有一个致命的错误是开始传递一些 references 指向其实并不存在的对象。例如企图实现一个返回 reference 的函数来替代 pass-by-value:

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

这种实现的问题在于:这个函数返回一个 reference 指向 result ,但 result 是个 local 对象,而 local 对象在函数退出之前就被销毁了,所以这个 reference 指向一个”从前的 Rational 对象“。

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

这种实现的问题在于:谁该对这个 new 出来的对象进行释放操作?并且很有可能因为客户的调用而直接导致内存泄漏:

Rational w, x, y, z;
w = x * y * z;

即使客户有意识的删除 w 对象,但是这行代码中调用了两次 new,其中一个 new 出来的空间已经泄漏。

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

这种实现方式有两个缺陷:

  • 线程不安全,所有线程共享 static 对象;

  • 共享 static 导致的问题,比如 (a * b) == (c * d) 永远被判定为 True;

综上,一个必须返回新对象的函数的正确写法就是让那个函数返回一个新对象。

Last updated

Was this helpful?