gpt4 book ai didi

c++ - 如何将值从std :optional without calling the destructor?中移出

转载 作者:行者123 更新时间:2023-12-03 16:09:34 26 4
gpt4 key购买 nike

我正在尝试编写一个函数make_foo,它将“解包”一个std::optional< foo >,返回包含的值。
该函数假定使用了可选参数,因此不对optional执行任何运行时检查。
下面是我的实现以及编译后的程序集,以供引用。
关于编译器输出,我有几个问题:

  • 为什么这会导致分支代码? optional::operator*提供对包含的值的未经检查的访问,因此我不希望看到任何分支。
  • 为什么调用foo的析构函数?注意在程序集中对on_destroy()的调用。我们如何在不调用析构函数的情况下将包含的值移出可选值?

  • Godbolt link
    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

    最佳答案

    How to move a value out of a std:optional without calling the destructor?


    就像您在示例中所做的一样。析构函数不会被 move 调用。 foo的析构函数由 std::optional的析构函数调用,该函数通过销毁您创建的临时 std::optional对象来调用。
    您只能通过泄漏对象或首先避免对象的创建(以及因此避免 move )来防止对象被破坏。

    Why does this result in branching code?

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

    optional::operator* gives unchecked access to the contained value, so I would not expect to see any branching.


    从理论上讲,如果优化器足够聪明,则可以使用该知识无条件调用析构函数,因为如果函数返回空 std::optional,则它可能知道程序的行为是不确定的。似乎还不够聪明,无法做出这样的优化。

    关于c++ - 如何将值从std :optional without calling the destructor?中移出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66747577/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com