You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

存储std::shared_ptr<T>时返回T&引用的最佳实践

存储std::shared_ptr时返回T&引用的最佳实践?

嘿,这个场景我平时写C++代码也经常碰到,咱们来拆解一下最佳实践,顺便给你的实现提几个实用的优化点~

首先,你原来的实现return *lastLocation.get()其实可以简化——因为std::shared_ptr重载了operator*,直接写return *lastLocation就可以了,没必要多调用一次get(),代码更简洁。

接下来是核心的安全和设计问题,咱们分点说:

  • 先确保shared_ptr非空,避免未定义行为
    如果你直接解引用空的shared_ptr,会触发未定义行为(大概率程序崩溃),所以必须先检查指针状态。常见的处理方式有两种:

    1. 初始化时就保证lastLocation永远不为空(比如在类的构造函数里就用std::make_shared<Point>初始化),这样函数里可以直接返回引用;
    2. 在getLastLocation()里主动检查,为空就抛出异常,给调用者明确的错误提示:
      #include <stdexcept>
      
      Point& MyClass::getLastLocation() {
          if (!lastLocation) {
              throw std::runtime_error("Last location has not been initialized yet");
          }
          return *lastLocation;
      }
      

    抛出异常是合理的,因为返回引用的语义就是“一定能拿到有效的对象”,空值属于异常情况。

  • 遵循const正确性原则
    如果这个函数只是用来读取lastLocation的内容,不需要修改Point对象,那应该返回const Point&,同时把成员函数声明为const,这样能避免调用者意外修改内部状态,也符合C++的设计规范:

    const Point& MyClass::getLastLocation() const {
        if (!lastLocation) {
            throw std::runtime_error("Last location has not been initialized yet");
        }
        return *lastLocation;
    }
    
  • 允许为空?试试std::optional<Point&>(C++17及以上)
    如果业务逻辑允许lastLocation为空,而且你不想用抛出异常的方式处理,C++17引入的std::optional可以返回一个“可选的引用”,让调用者自己判断是否有有效值:

    #include <optional>
    
    std::optional<Point&> MyClass::getLastLocation() {
        if (lastLocation) {
            return *lastLocation;
        }
        return std::nullopt;
    }
    

    调用的时候可以这样处理:

    if (auto lastLoc = obj.getLastLocation()) {
        // 拿到有效引用,直接操作
        lastLoc->x = 100;
    } else {
        // 处理空值的情况
        std::cout << "No last location recorded" << std::endl;
    }
    

    注意:std::optional存储引用需要C++17及以上支持,而且要保证返回的引用生命周期安全——只要lastLocation还持有对象,引用就有效。

  • 绝对避免返回悬空引用
    一定要确保返回的引用指向的对象,生命周期至少和调用者使用它的时间一样长。因为lastLocation是类的成员shared_ptr,只要类实例还活着,shared_ptr就会维持对象的生命周期,所以返回的引用是安全的。但千万别犯这种错误:

    // 错误示例!临时shared_ptr会在函数结束时销毁,返回的引用悬空
    Point& BadGetLocation() {
        std::shared_ptr<Point> temp = std::make_shared<Point>();
        return *temp;
    }
    

总结一下:优先保证shared_ptr非空,返回引用前做检查;只读场景用const Point&;允许为空且C++17+可用std::optional;绝对杜绝悬空引用。

内容的提问来源于stack exchange,提问作者Daniel Meltzer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:50:50