上一章 说了 尽量以传引用的方式 代替 传值
上一篇
本篇说一下 有些地方是不能返回引用的 !
参考 effective c++ 21条款
自从上一篇说了 传const引用要比传值效率高多了
我们就想在所有的地方都使用 pass -by - reference ,保证纯度
我们就犯了致命的错误 传递一些 reference 指向一些并不存在的对象 。
看个类
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
private:
int numerator;
int denominator;
friend const Rational operator* (const Rational& lhs, const Rational& rhs);
};
这个类 operator* 以传值的方式 返回一个 Rational 对象
既然我们知道了 传值带来的 构造和析构的代价 我们就改为 传引用的方式 看下面
Rational a(1,2);
Rational b(3,4);
Rational c = a*b;
既然接收的c 是个对象 那我们的函数实现就要创建一个对象
有两种方式
1 .创建局部对象 在 stack 上
2. 创建heap 对象 在 heap上
先看第一种的实现
friend const Rational& operator* (const Rational& lhs, const Rational& rhs)
{
Rational result(lhs.numerator * rhs.numerator,
lhs.denominator * rhs.denominator);
return result;
}
你可以拒绝这种写法
因为
- reference 不能指向一个已经销毁的对象 局部对象 这个是很错误的决定
- 里面还是实例化了一个对象 还是调用了构造,不是我们想要的效果
那我们实现第二种写法在 堆heap上创建对象
friend const Rational& operator* (const Rational& lhs, const Rational& rhs)
{
Rational *result = new Rational(lhs.numerator * rhs.numerator,
lhs.denominator * rhs.denominator);
return *result;
}
还是避免不了 一个构造函数的代价 但是解决了 引用指向的对象是个已经销毁的对象了
又出现了个新问题? 你new 的谁给你delete ?
这样就造成内存泄露了啊
你说可以delete 引用就可以了
看下面
把上面返回引用 改成 下面的返回指针倒是可以
Ration w,x,y,z;
w = x* y*z;
上面代码 调用两次 new 你怎么delete ??
所以这两张写法都不行
一个必须返回新对象的代码可以写成下面的形式
friend inline const Rational operator* (const Rational& lhs, const Rational& rhs)
{
return Rational(lhs.numerator * rhs.numerator,
lhs.denominator * rhs.denominator);
}
返回了一个新对象 ,然而还是没有避免 构造的代价
注意:
当我们必须在 返回一个reference 和 返回一个 object 之间选择时
你的工作就是挑选出正确的方法,至于效率是必须承受的
记住:
千万不要返回一个 指针pointer 或者 引用 reference 指向一个 local 局部对象
或者返回一个引用指向一个heap的对象