返回大对象或指示未找到该对象的正确方法

MK.*_*MK. 3 c++ c++17

执行此操作的惯用 C++ 方法是什么?我有一个如下所示的方法:

LargeObject& lookupLargeObject(int id) {
  return largeObjects[id];
}
Run Code Online (Sandbox Code Playgroud)

这是错误的,因为如果您使用不存在的 id 调用它,它将创建一个大对象的新实例并将其放入容器中。我不想要这样。我也不想抛出异常。我希望返回值表明未找到对象(因为这或多或少是正常情况)。所以我的选项要么是指针,要么是可选的。我理解并喜欢指针,但感觉 C++ 不想让我再使用指针了。接下来是选项。我将返回一个可选的,然后调用者看起来像这样:

std::optional<LargeObject> oresult = lookupLargeObject(42);
LargeObject result;
if (oresult) {
  result = *oresult;
} else {
  // deal with it
}
Run Code Online (Sandbox Code Playgroud)

它是否正确?感觉有点糟糕,因为我似乎在这里创建了 LargeObject 的 2 个副本?返回可选值时一次,将可选值提取到结果中时一次。一定有更好的方法吗?

Cor*_*sto 5

由于您不想返回指针,但也不想引发异常,并且您可能需要引用语义,所以最简单的方法就是返回std::optional<std::reference_wrapper<LargeObject>>.

代码如下所示:

std::optional<std::reference_wrapper<LargeObject>> lookupLargeObject(int id) {
    auto iter = largeObjects.find(id);
    if (iter == largeObjects.end()) {
        return std::nullopt;
    } else {
        return std::ref(iter->second);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 C++17,您甚至可以在 -conditioniter内声明变量if

调用查找函数并使用引用看起来像这样(这里在if-condition 内有变量声明):

if (auto const lookup_result = lookupLargeObject(42); lookup_result) {
   auto& large_object = lookup_result.value().get();
   // do something with large_obj
} else {
  // deal with it
}
Run Code Online (Sandbox Code Playgroud)