当我可以返回指针时,为什么要使用boost :: optional

nap*_*con 7 c++ c++11 boost-optional

如果我有一个find有时无法找到所需内容的函数,我倾向于使该函数返回一个指针,使得a nullptr指示找不到该东西.

例如

Student* SomeClass::findStudent(/** some criteria. */)
Run Code Online (Sandbox Code Playgroud)

如果Student存在,它将返回指向找到的Student对象的指针,否则它将返回nullptr.

我也看到了boost::optional为这个目的而提倡的.例如,当你想要实现一个可以返回"nothing"的函数时,何时使用boost :: optional以及何时使用std :: unique_ptr?

我的问题是,在这种情况下,没有返回指针是最佳解决方案.即,有可能找不到查询的项目,在这种情况下返回nullptr是一个完美的解决方案.使用类似boost::optional(或任何其他类似解决方案)的东西有什么好处?

请注意,在我的示例中,findStudent只会返回指向由其拥有的对象的指针SomeClass.

Bar*_*rry 10

optional<Student&>这里返回类型的优点是使用的语义对于所有熟悉的用户来说是optional显而易见的(并且一旦他们熟悉它就会变得很明显).那些语义是:

  • 调用者不拥有Student并且不负责内存管理.调用者只是获取对现有对象的引用.
  • 很明显,这个功能可能会失败.你可能得到一个价值,你可能什么得不到.很明显,呼叫者需要以某种方式检查结果.

optional<T>以某种方式自我记录T*.此外,它还有其它好处,因为它可以在您想要返回任何类型的对象类型而无需分配的情况下工作.如果你需要退回intdoubleSomePOD怎么办?

  • `optional&lt;T&amp;&gt;` 在该类型的当前 TS 版本中是明确非法的。`optional` 用于值类型。 (2认同)

Yak*_*ont 5

optional<T&>从C ++标准化轨道中除去,因为它的使用是有问题的:它的行为几乎相同于非拥有T*具有略微不同的(以及从混淆的不同optional<T>T*)语义。

optional<T&>基本上是一个没有所有权的T*漂亮包裹,有点奇怪。


现在,optional<T>是另一种野兽。

我已经optional<Iterator>在基于容器的查找算法中使用过。end()我没有返回,而是返回了空的Optional。这使用户无需进行比较就可以确定他们是否未能找到该项目,并使代码如下:

if(linear_search_for( vec, item))
Run Code Online (Sandbox Code Playgroud)

同样的算法也可以让您同时获得项目项目在容器中的位置(如果您确实需要的话)。

指向元素的指针不会为您提供所需的位置信息,除非使用连续的容器。

所以在这里,我创建了一个可为空的迭代器,它具有迭代器(通常使用不同类型的容器)和指针(可以测试为空状态)的优点。

下一个用途实际上是返回一个值。假设您有一个计算矩形的函数。

Rect GetRect();
Run Code Online (Sandbox Code Playgroud)

现在,这很棒。但是,如果这个问题可能毫无意义呢?好吧,一种方法是返回一个空的rect或其他“标志”值。

可选使您可以传达它可以返回一个rect或不返回任何内容,并且不将空rect用于“ nothing”状态的信息。它使返回值可为空。

int GetValue();
Run Code Online (Sandbox Code Playgroud)

是一个更好的例子。无效的值可以使用int的标志状态(例如)-1,但这会迫使函数的每个用户查找并跟踪标志状态,而不是无意中将其视为正常状态。

相反,要optional<int> GetValue()明确指出它可能会失败以及失败的状态。如果已填充,则知道它是一个实际值,而不是标志值。

在这两种情况下,返回非拥有指针都是不可行的,因为谁拥有存储?返回一个拥有的指针很昂贵,因为无意义的堆分配是无意义的。

可选的是可空值类型。当您想在本地管理资源,而您仍然想要一个空状态时,它们会使其清楚。


要研究的另一件事expected是提出的类型。这是可选的,但是在处于空状态时包含其为空的原因