如何在不调用析构函数的情况下将值移出 std:optional ?

乔尼波顿

我正在尝试编写一个函数,make_foo,它将“解开” a std::optional< foo >,返回包含的值。该函数假定可选的已启用,因此不会对optional.

我的实现如下,以及编译后的程序集以供参考。我有几个关于编译器输出的问题:

  1. 为什么这会导致代码分支?optional::operator*提供对包含值的未经检查的访问,所以我不希望看到任何分支。

  2. 为什么foo会调用析构函数?注意on_destroy()程序集中的调用我们如何在不调用析构函数的情况下将包含的值移出可选项?

Godbolt 链接

C++17 源代码

#include <optional>

extern void on_destroy();

class foo {
  public:
    ~foo() { on_destroy(); }
};

extern std::optional< foo > foo_factory();

// Pre-condition: Call to foo_factory() will not return nullopt
foo make_foo() {
    return *foo_factory();
}

优化的编译器输出 (Clang 11)

make_foo():                           # @make_foo()
        push    rbx
        sub     rsp, 16
        mov     rbx, rdi
        lea     rdi, [rsp + 8]
        call    foo_factory()
        cmp     byte ptr [rsp + 9], 0
        je      .LBB0_2
        mov     byte ptr [rsp + 9], 0
        call    on_destroy()
.LBB0_2:
        mov     rax, rbx
        add     rsp, 16
        pop     rbx
        ret
埃罗里卡

如何在不调用析构函数的情况下将值移出 std:optional ?

就像您在示例中所做的那样。析构函数不会被移动调用。的析构函数foo您创建std::optional的临时std::optional对象的析构函数调用的析构函数调用

您只能通过泄漏对象或首先避免对象的创建(以及移动)来防止对象被破坏。

为什么这会导致代码分支?

的析构函数中有一个分支std::optional仅当std::optional不为空时才调用所包含对象的析构函数

optional::operator* 提供对包含值的未经检查的访问,所以我不希望看到任何分支。

理论上,如果优化器足够聪明,它可能会使用这些知识无条件地调用析构函数,因为如果函数返回一个空的 ,它可能知道程序的行为是未定义的std::optional它似乎不够聪明,无法进行这样的优化。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

是否可以在不调用 std async 的情况下使用阻塞析构函数创建 std 未来?

如何从std :: optional <T>移动

如何脱离std :: experimental :: optional?

使用std :: optional参数调用函数

如何在C ++中使用std :: optional

如何在C ++中使用std :: optional?

constexpr函数内部的std :: experimental :: optional

对std :: optional的转发参考构造函数的约束

std :: optional是否更改函数的签名?

禁用std :: optional的转发构造函数

std :: optional的值的地址稳定吗?

std :: optional与“未使用/默认”值的用法

将nullptr转换为std :: optional

如何向上转换静态 std::optional

std :: optional在引擎盖下如何工作?

如何为std :: optional <T>分配“无”?

如何boost :: serialize std / boost :: optional?

为什么std :: optional构造函数使用std :: in_place?

std :: function <std :: optional <T>()>如何与返回T的lambda兼容?

如何在构造函数中使用std :: optional?

如何在结构中将值传递给std :: optional?

将一个std :: optional转换为另一个std :: optional

std :: optional延迟初始化如何?/ std :: optional如何实现?

如何将包含 std::unique_ptr 的 std::optional 结构传递给函数?

std::optional 不可复制?

在哪种情况下std :: optional运算符==会导致未定义的行为?

C ++标准是否允许在没有开销的情况下实现std :: optional <double>

std :: experimental :: optional <T>实现:Constexpr构造函数混淆

在 noexcept 函数体中处理 std::optional 是否安全?