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

NoS*_*tAl 22 c++ boost unique-ptr c++11 boost-optional

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

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

boost::optional<Person> findPersonInList();
Run Code Online (Sandbox Code Playgroud)

要么

std::unique_ptr<Person> findPersonInList();
Run Code Online (Sandbox Code Playgroud)

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

Mat*_* M. 25

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

如果您想要退回手柄:

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

都是可以接受的选择.我倾向于使用一个Ptr<Person>在无法访问的情况下抛出的类,但那是我的偏执狂.

如果您想要退回副本:

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

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

  • @MatthieuM.[回答]回复你的评论:"NotFound"显然是首选,因为它更直接地表达了语义.但是,我认为抛弃这种背景并不是一个好的选择. (5认同)
  • 不要使用指针,你不必抛出null访问(你几乎不应该有空指针). (4认同)
  • @CatPlusPlus:那么,你宁愿抛出`NotFound`而不是`NullPointer`?有什么不同 ? (4认同)

Kon*_*lph 14

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


And*_*hko 8

boost::optional更清楚地说明你的意图.您需要明确记录该空std::unique_ptr表示没有值返回

  • 我不同意,一个空指针(无论是原始的还是智能的)已经标志着*几十年没有结果*,它是无处不在的. (4认同)
  • @MatthieuM.:可能我解释错了.如果一个函数返回一个std :: unique_ptr,那么它不能返回任何值是不明显的,因为总是返回一些东西的类似函数会有相同的签名 (4认同)
  • @MatthieuM正如你所说,一个空指针已经表示几十年没有结果 - 并不意味着这是一个好主意:[link](http://lambda-the-ultimate.org/node/3186 )Tony Hoare /历史上不好的想法:"空的参考:十亿美元的错误"摘要:我称之为十亿美元的错误.它是1965年空引用的发明.那时,我正在设计第一个用于面向对象语言(ALGOL W)的引用的综合类型系统...... (4认同)
  • @MatthieuM."更清楚地表明你的意图"是明确的.`boost :: optional`的*目的*是说明这个特定的意图.所以它 - 几乎是定义 - 更清晰.这里没有任何不同意见,这是一个事实论点.此外,你忘记了`unique_ptr`的固有语义:它发出信号(独占)*所有权*. (3认同)
  • @KonradRudolph:我同意`boost :: optional`更清楚地表明意图,但如果你看看我的答案,你会发现它有潜在的问题.它意味着包含一个值,而不是一个动态分配的类,因此不适合所拥有的多态类实例.*有*你使用`std :: unique_ptr`,并且没有必要将它包装在顶部的`boost :: optional`中以表示它可能为null. (3认同)

ibi*_*man 6

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

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

  • 对我来说,异常开销不是在运行时,而是在源代码中.try-catch引入了*两个*独立的范围,你需要体操甚至从它们中获取任何东西(即你需要从try-catch中声明一个变量,所以你可以在以后使用它;你是否会使一切都默认可构造?). (3认同)

Bar*_*icz 5

啊,Xeo没出现呢?

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

  • unique_ptr意味着我拥有一个物体.这只是说"我是一个对象"的不同方式.因此,null unique_ptr是可以引起注意的东西.我期待一个物体,但我一无所获; 代码一定是错的!
  • optional意味着我有时可能没有初始化,但没关系.在这种情况下,没有后顾之忧; 如果是的话None,那就是被人们想到的行为.

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

关于你的例子的结论:find应该返回optional.

  • 我不明白这种对'unique_ptr`的恐惧.C++标准中没有任何内容表明`unique_ptr`不应为null.并且null"unique_ptr"完美地表达了"未找到".就像`optional`一样."可选"的真正优势在于,您不必像Matthieu所说的那样支付动态内存分配的成本. (2认同)