我正在尝试编写一个函数make_foo
,它将“解包装”std::optional
,返回包含的值。该函数假设optional已被使用,因此不对optional
执行任何运行时检查。
下面是我对此的实现,以及编译后的程序集以供参考。关于编译器输出,我有几个问题:
>
为什么这会导致分支代码?optional::operator*
允许对包含的值进行未经检查的访问,因此我不希望看到任何分支。
为什么调用foo
的析构函数?请注意程序集中对on_destroy()
的调用。如何在不调用析构函数的情况下将包含的值移出可选值?
Godbolt连杆
#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
,它可能知道程序的行为是未定义的。做这样的优化似乎不够聪明。
你的方法或多或少是这样的:
foo make_foo() {
auto x = foo_factory();
return *x;
}
其中x
是从工厂返回的option
(在代码中未命名为临时)。当x
被销毁时,它要么调用所包含对象的析构函数(当有一个时)。或者它不破坏包含的对象(当没有对象时)。简而言之:您移出的foo
仍然需要销毁,即使您知道可选内容包含它,编译器也不能销毁,因此产生了分支。
如何在不调用析构函数的情况下将值移出std:optional?
你不能。即使是一个移动的物体,最终也需要被销毁。
问题内容: 注意:我在使用React Native时遇到了这个特定的问题,但是我想这也同样适用于React。 我有一个使用React.Component构建的React组件。我不需要设置状态,但是我有道具。我建议的语法如下: 我知道我可以使用函数来构造此组件,如下所示: 但是我更喜欢前者,因为我的组件会增长,可能会有状态等,我只想以相似的方式构建所有组件。 现在,我的linter抱怨拥有一个无用的
问题内容: 在Mongoose的早期版本(针对node.js)中,可以选择使用它而不定义架构 但是在当前版本中,“ noSchema”功能已被删除。我的架构可能会经常更改,并且实际上不适合已定义的架构,因此,是否有一种新的方式在猫鼬中使用无架构的模型? 问题答案: 我想这就是您要寻找猫鼬严密的东西 选项:严格 严格选项(默认情况下启用)可确保未在架构中指定的添加到模型实例的值不会保存到数据库中。
我有一个类,它有一个默认构造函数,还有一个重载构造函数,它接受一组参数。这些参数与对象上的字段匹配,并在构造时指定。此时,我需要用于其他目的的默认构造函数,因此如果可以的话,我希望保留它。 我的问题:如果我删除默认的构造函数并传递JSON字符串,对象反序列化正确,并传递构造函数参数没有任何问题。我最终以我所期望的方式找回填充的对象。但是,一旦我将默认构造函数添加到对象中,当我调用
问题内容: 我有两个活动,我分别从这两个活动向Firestore添加数据。但是,每当我向Firestore添加第二个活动数据时,它就会覆盖第一个活动数据。我在以下两个活动中使用了以下代码: 如何停止覆盖?我想将两个“活动”数据保存在同一文件夹中。 问题答案: 我建议您再添加一个文档或集合,以便它可以为单个用户存储多个数据值。 您可以为两个活动创建文档参考: 或者,您可以为其创建一个子集合: 更多关
假设我有一个未来对象的列表<代码>列表 但此方法必须等待所有期货返回,然后才能返回流 我想让它像管道一样工作,上层从流中提取数据并根据需要进行处理,无需等待所有的未来完成。