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

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


核心思想

C++ 中绝不要返回指针或引用指向以下几种对象:

  1. 局部栈对象 (local stack object)

    • 当函数返回时,栈对象会被销毁,指针或引用将指向一个无效的内存地址,导致未定义行为。
  2. 堆分配对象 (heap-allocated object)

    • 返回指针或引用可能导致资源泄漏,因为调用者必须记得手动释放资源,容易出错。
  3. 局部静态对象 (local static object)

    • 如果同时需要多个这样的对象,返回引用会导致数据竞争和意外的共享状态问题。

推荐解决方案

当必须返回一个对象时,建议 返回值对象,这样可以依赖编译器的 返回值优化 (RVO)移动语义 来避免性能损耗。


示例代码

// 安全的返回对象示例
inline const Rational operator* (const Rational& lhs, const Rational& rhs) {
    return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
}

上述代码返回了一个新的 Rational 对象,而不是返回一个指向临时对象的指针或引用。这种方式既直观又安全,依赖编译器优化,不会导致性能损耗。


禁止的用法

以下代码示例会引发问题:

  1. 返回局部栈对象的引用
const Rational& multiply(const Rational& lhs, const Rational& rhs) {
    Rational result(lhs.n * rhs.n, lhs.d * rhs.d); // 栈对象
    return result; // 返回的引用无效
}
  • 问题result 是局部栈对象,函数返回后被销毁,引用将指向无效内存。
  1. 返回堆对象的引用
const Rational& multiply(const Rational& lhs, const Rational& rhs) {
    Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d); // 堆分配
    return *result; // 调用者需要手动释放
}
  • 问题:调用者必须记得释放 result,否则会造成内存泄漏。
  1. 返回静态局部对象的引用
const Rational& multiply(const Rational& lhs, const Rational& rhs) {
    static Rational result(lhs.n * rhs.n, lhs.d * rhs.d); // 静态对象
    return result; // 多次调用会共享同一对象
}
  • 问题:如果函数被多次调用,不同调用会共享 result,容易引发数据竞争和意外行为。

结论

  1. 遇到返回对象时,优先 返回值对象,避免使用指针或引用。
  2. 借助现代编译器优化,返回值对象的性能损耗可以忽略不计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值