何时使用boost :: optional以及何时使用std :: unique_ptr,如果你想实现一个可以返回“nothing”的函数?

时间:2013-01-16 14:31:57

标签: c++ boost c++11 unique-ptr boost-optional

根据我的理解,有两种方法可以实现有时不返回结果的函数(例如,在ppl列表中找到的人)。

* - 我们忽略原始ptr版本,与bool标志配对,以及未找到版本时的异常。

boost::optional<Person> findPersonInList();

std::unique_ptr<Person> findPersonInList();

那么有什么理由可以优先考虑另一个吗?

7 个答案:

答案 0 :(得分:25)

取决于:您希望返回句柄还是副本

如果您想返回句柄

  • Person*
  • boost::optional<Person&>

都是可以接受的选择。我倾向于使用Ptr<Person>类,如果是空访问则会抛出,但那是我的偏执狂。

如果您想要返回副本

  • boost::optional<Person>非多态类
  • std::unique_ptr<Person>用于多态类

因为动态分配会产生开销,因此您只能在必要时使用它。

答案 1 :(得分:14)

一般答案是,您的意图由boost::optional表示,而不是由std::unique_ptr表示。也就是说,你的find操作的特殊情况应该符合标准库的方式,假设您的基础类型具有迭代器的概念:如果没有元素,则将迭代器返回end()找到了,否则就是元素的迭代器。

答案 2 :(得分:8)

boost::optional更明确地表明了你的意图。您需要明确记录空std::unique_ptr表示没有值返回

答案 3 :(得分:6)

有第四种方法:如果找不到任何内容,则使函数抛出异常。

我知道这并没有真正回答你的问题因此我道歉但也许你没想过。

答案 4 :(得分:5)

啊,Xeo还没出现?

好吧,我告诉过你一次,我会再说一遍:这两个是完全不同的用途,目的不同。

  • unique_ptr表示我拥有一个对象。这只是说“我是一个对象”的不同方式。因此,null unique_ptr可以引起注意。我期待一个物体,但我一无所获;代码一定是错的!
  • optional表示我有时可能未初始化,但没关系。在这种情况下,没有后顾之忧;如果它是None,那就是被认为的行为。

两者都隐含地转换为bool这一事实并不意味着它们可以相互兼容使用。使用optional代码可能不会产生任何输出(例如,读取流)。在工厂对象中使用unique_ptr; 最有可能为您创建一个对象,如果没有,则抛出异常。

关于您的示例的结论:find应返回optional

答案 5 :(得分:2)

从概念上归结为这个,考虑到可以为空的要求:

std::optional具有值语义,堆栈存储。

std::unique_ptr已移动语义,堆存储。

如果您需要值语义和堆存储,请使用std::indirect http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0201r1.pdf

(如果你想要移动语义和堆栈存储......我不知道。我猜它是带有堆栈分配器的unique_ptr?)

答案 6 :(得分:1)

  

那么有什么理由可以优先考虑另一个吗?

他们表达了截然不同的意图:optional表示该函数可能无法给出结果(这不是错误情况)。 unique_ptr告诉你一些关于所有权语义的东西(并且更容易使用null来表示错误)。

通常我会使用最能表达界面背后意图的那个。

例如,考虑您正在编写HTTP服务器,该服务器尝试将收到的缓冲区解析为HTTP请求对象。当您尝试解析不完整的缓冲区时,没有错误情况,您只需等待并缓冲更多数据,然后再试一次。

我会使用optional表达这一点,以明确该函数可能不返回任何内容(并且不返回任何内容不是错误情况)。

如果我的解析必须验证内容(例如,如果解析的表达式是无效的正则表达式,则正则表达式解析器应该产生错误)我将返回null unique_ptr,或者更好的是,抛出异常。