引用类型返回函数:如何返回(可选)对象

ABC*_*lus 0 c++ reference

我有一个多线程C++应用程序,它可以从任何线程调用类似下面的函数,从列表/向量中获取一个Object.

class GlobalClass{
public:
     MyObject* GlobalClass::getObject(int index) const
     {
          /* mutex lock & unlock */

          if (m_list.hasValueAt(index))
              return m_list[index];
          else
              return 0;
     }
List<MyObject*> m_list;
};

//Thread function
MyObject* obj = globalClass->getObject(0);
if (!obj) return;
obj->doSomething();
Run Code Online (Sandbox Code Playgroud)

注意:这里的范围是通过引用,值或指针来理解与函数返回相关的一些最佳实践,因此请原谅一些伪代码或缺少声明(我使用锁定/解锁,GlobalClass是全局单例等等) .

这里的问题是,如果MyObject在那个索引中删除里面GlobalClass,在某一点上我使用了一个坏指针(obj).

所以我在考虑返回该项目的副本:

     MyObject GlobalClass::getObject(int index) const
     {
          /* mutex lock & unlock */

          if (m_list.hasValueAt(index))
              return MyObject(*m_list[index]);
          else
              return MyObject();
     }
Run Code Online (Sandbox Code Playgroud)

这里的问题是MyObject返回的object()是一个足够大的对象,返回副本效率不高.

最后,我想返回对该对象的引用(更好的const引用):

     const MyObject& GlobalClass::getObject(int index) const
     {
          /* mutex lock & unlock */

          if (m_list.hasValueAt(index))
              return *m_list[index];
          else{
              MyObject* obj = new MyObject();
              return *obj ;
          }
     }
Run Code Online (Sandbox Code Playgroud)

考虑到我的列表无法在该索引处加入对象,我引入了内存泄漏.

处理这个问题的最佳解决方案是什么?即使效率较低,或者在返回引用时我是否缺少某些内容,我是否必须退回复制副本?

Hap*_*tus 5

你有多种选择:

  1. 使用std::shared_ptrif"Get"将对象的拥有权传递给调用者.这样对象就不会超出范围.当然,调用者在发生这种情况时并不知道.
  2. 用一个std::weak_ptr.这与1具有相同的含义,但ptr可以重置.在这种情况下,调用者可以检测对象是否被删除.
  3. std::optional按照评论中的建议使用,并返回副本或引用.使用引用类型作为可选参数不能避免对象被删除的问题,因此引用也可能变得无效.副本可以避免这种情况,但它可能过于昂贵,如上所述.

通过这些行读取,您似乎建议调用者在调用后立即使用指针,并在有限的时间内使用.所以1.和2.是等价的,似乎符合你的需要.

有关更多详细信息,请参阅智能指针的介绍.