将可选与reference_wrapper相结合是否有意义?

Does it make sense to combine optional with reference_wrapper?

本文关键字:相结合 是否 有意义 wrapper reference      更新时间:2023-10-16

我突然想到,在C++可以使用类型std::optional<std::reference_wrapper<T>>.这种类型的对象本质上是对类型为T或 null 值的对象的引用,即几乎是一个指针。我的问题:

  1. std::optional<std::reference_wrapper<T>>T*之间有什么概念上的区别吗?

  2. 有什么实际区别吗?在某些情况下,选择std::optional<std::reference_wrapper<T>>而不是T*可能是可取的?

std::optional<std::reference_wrapper<T>>T*之间有什么概念上的区别吗?

std::optional<>,顾名思义,是指当我们可能有一个值或可能根本没有任何值时使用。

相当于对T*对象没有值,就是给它分配nullptr,即:指针将指向任何地方,而不是某处(甚至任何地方,即:未初始化)。可以说,std::optional<>导出了指向任意类型的指针的nullptr概念。所以,我想说它们在概念上非常相似,是一种概括std::option<>方法。

有什么实际区别吗?在某些情况下,选择std::optional<std::reference_wrapper<T>>而不是T*可能是可取的?

我能想到大小。std::optional<>包含一个内部标志,用于指示值的存在/不存在,而对于T*nullptr直接编码为指针可以存储的值之一。所以一个std::optional<std::reference_wrapper<T>>对象将大于一个T*

在安全性方面,与T*不同,std::optional<>提供了成员函数value()如果没有值,则抛出异常(它提供与T*一样不安全的operator*())。

此外,例如,使用std::optional<std::reference_wrapper<T>>而不是T*作为函数的返回值可能会以更明确的方式指示可能根本没有值。

std::optional<std::reference_wrapper<T>>T*之间的主要区别在于,对于T*,您必须考虑谁拥有所指向的内存。

如果一个函数返回T*你必须知道是你负责释放内存还是其他人负责释放内存。当它是参考时,这不是你必须关心的事情。

还有其他一些区别。 使用 T * 时,您有两种状态。 指针指向有效对象或 nullptr,这意味着空。

使用 std::optionalstd::reference_wrapper你有第三个状态:未初始化,指针本身还没有状态。

像这样想象:

void foo( std::optional<std::reference_wrapper<T>>& ref)
{
if (!ref)
{  // still not initialized
initialize_reference(ref);
}

现在您已经设置了引用,您可以检查它是否具有有效的指针。