我应该使用什么函数签名来返回对可能不存在的对象的引用? 我写的是C++中的一个简单容器类,类似于一个映射由键索引的对象的映射。我想提供访问器功能,例如: V& getValue(const K &key);

我应该使用什么函数签名来返回对可能不存在的对象的引用? 我写的是C++中的一个简单容器类,类似于一个映射由键索引的对象的映射。我想提供访问器功能,例如: V& getValue(const K &key);,c++,reference,parameters,C++,Reference,Parameters,其中,我返回值的引用 但我还希望处理键/值不存在的情况,并能够向用户返回一些状态(可能有一些原因导致不存在,我希望通过一些状态类型与调用者通信) 我想我可以执行以下操作,但是调用它需要先构造一个V对象,然后才能调用这个函数,我只是将内部V对象复制到一个通过引用传入的对象中,所以这看起来很糟糕 Status getValue(const K &key, V& v); 我还可以: V &getValue(const K &key, Status &s);

其中,我返回值的引用

但我还希望处理键/值不存在的情况,并能够向用户返回一些状态(可能有一些原因导致不存在,我希望通过一些状态类型与调用者通信)

我想我可以执行以下操作,但是调用它需要先构造一个V对象,然后才能调用这个函数,我只是将内部V对象复制到一个通过引用传入的对象中,所以这看起来很糟糕

Status getValue(const K &key, V& v);
我还可以:

V &getValue(const K &key, Status &s);
但出于某种原因,这似乎有点笨拙,因为焦点被从状态上移开,用户可能忘记检查它(但这可能不是我的问题)

那么,是否有一个类似于的函数

Status getValue(const K &key, V& v);
在调用虚拟V对象之前,是否需要构造虚拟V对象?您不能将引用传递给引用。我想我可以使用指针,我很乐意这样做,但创建一个简单易用的函数并对其进行推理是不可取的


有什么想法吗?

如果您不想使用boost,我会选择使用
boost::optional
,或者创建一个类似的模板。使用
boost::optional
时,您的函数将如下所示:

boost::optional<MyClass &> getValue(const K &key)
boost::可选的getValue(const K&key)

考虑返回
boost::variant
或(等效地)
boost::variant
我看到了3个选项:

  • 返回一个“包装器”对象,该对象可以转换为V&并且可以判断它是否存储了有效的引用(可以在V*附近实现)
  • 返回一个指针
  • 如果找不到键,则返回引用并引发异常

  • 我个人会使用指针。

    通常的解决方案是提供一个
    bool contains(const K&key)
    函数,如果您不希望访问者以静默方式创建条目,请让它抛出异常。(有两个访问器,一个抛出异常,另一个创建条目也是常见的)


    当然,这可能不是你想要的。您希望将所有这些功能整合到单个函数中的原因是什么?

    我将遵循std::map interface的一个想法:

    std::pair<iterator,bool> getValue(const K& key);
    
    std::pair getValue(const K&key);
    

    值对象可以通过迭代器访问,
    bool
    标志显示值是否存在。

    您可以使用原始函数
    V&getValue(const K&key)
    ,并引发异常以指示未成功的
    状态


    然后,调用方可以选择延迟处理问题的方式(通过让异常冒泡到适当的处理程序),但他们不能完全忘记它,因为否则程序将崩溃。呼叫站点不必充斥着状态检查和错误报告代码。

    首先,我将以书面形式回答您的问题:我建议返回一个
    boost::optional
    ,这样您仍然可以通过引用返回,但也可以选择返回


    但是,我不建议使用此接口。标准容器已经有了一个接口来解决这个问题,即返回迭代器而不是值。我建议只使用一个“迭代器”接口(它不一定是一个真正成熟的迭代器)并返回一个
    结束
    /结束后的一个,以表明没有找到iter,而不是通过引用返回或不返回。越是使容器的界面看起来像一个标准容器,您就越可以选择使用标准算法并将其插入任意位置作为替代。

    这是一个非常好的问题+1。我不太熟悉我喜欢的东西,如何在C++中最好地表达某些东西,这对帮助我有很大帮助,希望其他人能提高他们的技能。一般来说,你需要一些(任何类型)的包装器(安得烈和ECUMUR建议)。如果没有找到结果,返回null。“将某些状态返回给用户(可能有某些原因导致它不存在,我希望通过某些状态类型与调用者通信)”?您是对的,无法返回带有此签名的“状态”。不返回元素的唯一“正常”原因是“元素不存在”,对于其他所有内容,我将使用std::exception。这不是
    std::map
    接口;
    std::map
    中唯一返回
    std::pair
    的函数是
    insert
    ,并且
    bool
    指示是否成功插入了键值对。@Xeo:我的意思是遵循这个想法,而不是完全按照接口。如果返回迭代器,还可以返回
    end()
    迭代器(不,我不知道为什么stdlib没有这样做).无论如何,我知道为什么stdlib为
    insert
    返回迭代器和
    bool
    bool
    表示成功/失败,迭代器是新插入的元素或阻止插入的元素。这些语义对于
    getValue
    函数没有意义。通常的解决方案是提供一个布尔包含(const k& key)函数——通常在C++中……在C++中,通常提供一个<代码>查找< /C>函数,返回一个迭代器,它可以与()进行比较。-这样,您就不必重新启动搜索来对找到的对象进行操作。等价地,指针可能为NULL.True。我的意思不是说该声明是一个确切的答案,而且问题中缺少迭代器,这让我在回答中跳过了它们。