我正在尝试编写一个函数,make_foo
,它将“解开” a std::optional< foo >
,返回包含的值。该函数假定可选的已启用,因此不会对optional
.
我的实现如下,以及编译后的程序集以供参考。我有几个关于编译器输出的问题:
为什么这会导致代码分支?optional::operator*
提供对包含值的未经检查的访问,所以我不希望看到任何分支。
为什么foo
会调用析构函数?注意on_destroy()
程序集中的调用。我们如何在不调用析构函数的情况下将包含的值移出可选项?
#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();
}
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] 删除。
我来说两句