std::可选和多态性

std::optional and polymorphism

本文关键字:多态性 std      更新时间:2023-10-16

我在许多文章中读到堆栈溢出,当使用指针(用于参数或返回值)并且允许nullptr(使其可选)时,通常最好使用std::optional

但是,如果指针指向多态类型呢?最好使用std::optional还是指针?

optional不适用于多态类型。它是一种值类型,多态基类在optional中不起作用。就像把多态基类放在vector或类似的容器中一样不起作用。

返回一个指针。建议通常被称为"一般"是有原因的。

std::optional提案明确表示它不是多态的:

value_ptr要求在免费商店。这意味着sizeof(value_ptr<T>)是固定的而与CCD_ 10无关。value_ptr是"多态":类型为的对象value_ptr<T>可以指向从T派生的DT类型的对象。深度复制保留动态类型。可选不需要免费门店分配:其创建效率更高;事实并非如此"多态"。

您的选项可以归结为原始指针或unique_ptr。如果需要副本,请使用unique_ptr,否则请使用原始指针。

您可以编写多态伪可选。

您将希望使用有界对象大小/对齐(可能是参数)来实现小对象优化,并包括一个基类和一组可擦除的附加操作(如复制或移动)。我写了一个没有指针回退的有界多态类型,如果由于类似的原因缺少空间,它就无法编译,可能发布在SO.上的某个地方

Optional不是多态的,但正则值类型和伪正则值类型可以是多态的。Optional over pointers/smart-ptr的大多数参数实际上是使用正则和伪正则非分配类型的参数。

我在很多文章中读过stackerflow,当使用指针(用于参数或返回值)并且允许使用nullptr(使其成为可选)时,通常最好使用std::optional

假设您指的是使用std::optional来携带指针或引用以外的值。在这种情况下,您谈论的是参数中的可选值或的可选返回值


在参数中使用optional作为可选项有一个缺点,即对象被复制或至少被移动,这可能是不可取的。此外,它排除了多态性。

最简单的方法是使用指向const:的指针,这也避免了不必要的复制,并支持多态性

void foo( Some_type const* p_object )

但是,调用方必须在实际参数上使用&运算符。

为了简化调用,您可以将重载提供为语法加糖:

void foo() { foo( nullptr ); }
void foo( Some_type const& object ) { foo( &object ); }

它支持像这样的呼叫

foo();

foo( o );

使用optional作为返回值的优点是,当调用代码正确检查值是否存在时,可以避免异常抛出。但是

似乎排除了包装对象的普通RVO(返回值优化)–狡猾的词“出现";因为我看不到这方面的无懈可击的证据,但我仍然看不出RVO是如何做到的。因此,当没有返回值的情况很少见,和/或效率非常重要时,最好只是抛出一个异常C++只支持多态返回值的(原始)指针和引用,在这方面使用optional和抛出异常表示没有返回值没有区别。

对于多态可选返回值,您可以使用像std::unique_ptrstd::shared_ptr这样的智能指针来处理所有权。