我应该使用什么函数签名来返回对可能不存在的对象的引用?

时间:2012-08-15 14:16:50

标签: c++ reference parameters

我在C ++中编写一个简单的容器类,类似于存储由键索引的对象的映射。我想提供一个访问函数,例如:

V& getValue(const K &key);

我将引用返回给值。

但是我也想处理不存在键/值并且能够向用户返回某些状态的情况(可能有一些原因导致我不希望通过它回传给调用者一些状态类型)。

我想我可以执行以下操作,但是调用它需要在调用此函数之前构造V对象,并且我只是将内部V对象复制到通过引用传入的对象中,因此这看起来很糟糕。

Status getValue(const K &key, V& v);

我也可以这样做:

V &getValue(const K &key, Status &s);

但出于某些原因,似乎有点笨重,因为焦点被从状态中吸走,用户可能忘记检查它(但也许这不是我的问题)。

无论如何都有类似

的功能
Status getValue(const K &key, V& v);

在调用之前不需要构造虚拟V对象?您无法传递对引用的引用。我想我可以使用指针并且很乐意这样做,但是创建一个简单的使用和推理函数是不太可取的。

有什么想法吗?

7 个答案:

答案 0 :(得分:2)

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

当然,这可能不是你想要的。你想把所有这些都融入一个函数的原因是什么?

答案 1 :(得分:2)

您可以使用原始函数V& getValue(const K &key),并抛出异常以指示未成功的Status值。

然后,调用者可以选择延迟他们如何处理问题(通过让异常气泡到适当的处理程序),但是他们不能完全忘记它,否则程序会崩溃。呼叫站点不需要混杂状态检查和错误报告代码。

答案 2 :(得分:1)

如果您不想使用boost,我会使用boost::optional或创建类似的模板。使用boost::optional,您的功能将如下所示:

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

答案 3 :(得分:1)

我看到3个选项:

  1. 返回一个“包装”对象,可以将其转换为V&amp;并且可以判断它是否存储有效的引用(可以在V *周围实现)。
  2. 返回指针。
  3. 如果找不到密钥,则返回引用并抛出异常。
  4. 我个人会选择指针。

答案 4 :(得分:0)

考虑返回boost::variant<V &, Status>或(等效)boost::variant<std::reference_wrapper<V>, Status>

答案 5 :(得分:0)

我会遵循std :: map界面的想法:

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

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

答案 6 :(得分:0)

首先我会按照书面回答你的问题:我建议你回复一个boost::optional<boost::ref<V> >,这样你仍然可以通过引用返回,但也可以这样做。

但是,我不会建议这个界面。标准容器已经有一个解决这个问题的接口,即返回迭代器而不是值。我建议只使用一个“迭代器”接口(它不必是一个真正的完整迭代器)并在结束时返回一个end /一个来表示找不到iter,而不是返回通过引用与否。您使容器的界面看起来越像标准容器,您使用标准算法的选择就越多,并将其插入任何您想要替换的地方。