在 C 中返回“NULL 引用”?

新手上路,请多包涵

在 JavaScript 或 PHP 等动态类型语言中,我经常执行以下功能:

 function getSomething(name) {
    if (content_[name]) return content_[name];
    return null; // doesn't exist
}

如果对象存在,我返回一个对象,如果不存在,则返回 null

使用引用的 C++ 中的等价物是什么?一般有什么推荐的模式吗?我看到一些框架为此目的具有 isNull() 方法:

 SomeResource SomeClass::getSomething(std::string name) {
    if (content_.find(name) != content_.end()) return content_[name];
    SomeResource output; // Create a "null" resource
    return output;
}

然后调用者将以这种方式检查资源:

 SomeResource r = obj.getSomething("something");
if (!r.isNull()) {
    // OK
} else {
    // NOT OK
}

然而,必须为每个类实现这种神奇的方法似乎很繁重。此外,何时应将对象的内部状态从“null”设置为“not null”似乎并不明显。

这种模式有什么替代品吗?我已经知道可以使用指针来完成,但我想知道如何/是否可以使用引用来完成。还是我应该放弃在 C++ 中返回“null”对象并使用一些 C++ 特定的模式?任何有关正确方法的建议将不胜感激。

原文由 laurent 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

您不能在引用期间执行此操作,因为它们永远不应为 NULL。基本上有三种选择,一种使用指针,另一种使用值语义。

  1. 使用指针(注意:这要求资源在调用者有指向它的指针时不会被破坏;还要确保调用者知道它不需要删除对象):
    SomeResource* SomeClass::getSomething(std::string name) {
       std::map<std::string, SomeResource>::iterator it = content_.find(name);
       if (it != content_.end())
           return &(*it);
       return NULL;
   }

  1. 使用 std::pairbool 来指示项目是否有效(注意:要求 SomeResource 具有适当的默认构造函数并且构造成本不高):
    std::pair<SomeResource, bool> SomeClass::getSomething(std::string name) {
       std::map<std::string, SomeResource>::iterator it = content_.find(name);
       if (it != content_.end())
           return std::make_pair(*it, true);
       return std::make_pair(SomeResource(), false);
   }

  1. 使用 boost::optional
    boost::optional<SomeResource> SomeClass::getSomething(std::string name) {
       std::map<std::string, SomeResource>::iterator it = content_.find(name);
       if (it != content_.end())
           return *it;
       return boost::optional<SomeResource>();
   }

如果你想要值语义并且有能力使用 Boost,我推荐选项三。 boost::optional 优于 std::pair 的主要优点是统一化的 boost::optional 值不构造其封装的类型。这意味着它适用于没有默认构造函数的类型,并为具有非平凡默认构造函数的类型节省时间/内存。

我还修改了您的示例,因此您不会两次搜索地图(通过重用迭代器)。

原文由 Sven 发布,翻译遵循 CC BY-SA 3.0 许可协议

从 C++17 开始,您可以通过以下方式使用本机 std::optional (此处)

 std::optional<SomeResource> SomeClass::getSomething(std::string name) {
    if (content_.find(name) != content_.end()) return content_[name];
    return std::nullopt;
}

原文由 Mariam Elsayed 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题