侧边栏壁纸
博主头像
如此肤浅

但行好事,莫问前程!

  • 累计撰写 52 篇文章
  • 累计创建 6 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

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

如此肤浅
2022-05-28 / 0 评论 / 0 点赞 / 33 阅读 / 1,374 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-05-29,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. 绝不要返回 pointer 或 refcrcncc 指向一个 local stack 对象,或返回 reference 指向一个 heap-allocated 对象,或返回 pointer 或 reference 指向一个 local static 对象而有可能同时需要多个这样的对象。条款 4 已经为“在单线程环境中合理返回 reference 指向一个 local static 对象”提供了一份设计实例。

不正确地使用 reference 方式一

函数创建对象有两种方式:在 stack 空间或在 heap 空间创建。如果定义了一个局部变量,那么是在 stack 空间创建对象。

const Rational& operator*(const Rational& lhs, const Rational &rhs)
{
	Rational result(lhs.n * rhs.n, lhs.d * rhs.d);	// 很糟糕!
    return result;
}

上述代码中,result 对象是局部变量,在函数结束是便会被销毁。因此返回的 reference 指向了一个不存在的对象!!!

不正确地使用 reference 方式二

既然在 stack 中创建对象有问题,那在 heap 中构造对象呢?

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

在这种情况下使用者可能会忘记释放对象导致内存泄露。

不正确地使用 reference 方式三

将对象定义为 static 时会怎么样呢?

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

上述代码可能在多线程的情况下不安全。此外,对于下述代码:

bool operator==(const Rational& lhs, const Rational& rhs);
Rational a, b, c, d;
...
if((a * b) == (c * d)) {
	当乘积相等时,做适当的相应动作;
} else {
	当乘积不相等时,做适当的相应动作;
}

表达式 ((a * b) == (c * d)) 的值总是为 true,无论 a,b,c,d 的值是什么!

一旦将代码重新写为等价的函数形式,很容易就可以看出是什么原因了:

if(operator==(operator*(a, b), operator*(c, d)))

注意,在 operator== 被调用前,已有两个 operator* 调用式起作用,每一个都返回 reference 指向 operator* 内部定义的 static Rational 对象。因此 operator== 被要求将“operator* 内的 static Rational 对象值”拿来和“operator* 内的 staticRational 对象值”比较,所以值会永远为 true。

因此,对于一个必须返回新对象的函数,正确写法是就让它返回一个新对象。不必为了效率而误用 reference!!!

0

评论区