我认为用 std::nullopt
初始化 std::optional
与默认构造相同。
它们在 cppreference 被描述为 等价物,如形式 (1)
但是,Clang 和 GCC 似乎都以不同的方式对待这些玩具示例函数。
#include <optional>
struct Data { char large_data[0x10000]; };
std::optional<Data> nullopt_init()
{
return std::nullopt;
}
std::optional<Data> default_init()
{
return {};
}
编译器资源管理器似乎暗示 使用 std::nullopt
将简单地设置 一个字节 的“包含”标志,
nullopt_init():
mov BYTE PTR [rdi+65536], 0
mov rax, rdi
ret
虽然默认构造将对类的每个字节进行 _值初始化_。这在功能上是等效的,但几乎总是更昂贵。
default_init():
sub rsp, 8
mov edx, 65537
xor esi, esi
call memset
add rsp, 8
ret
这是故意行为吗?什么时候应该首选一种形式而不是另一种形式?
更新:GCC(自 v 11.1 起)和 Clang(自 v 12.0.1 起) 现在可以有效地处理这两种形式。
原文由 Drew Dormann 发布,翻译遵循 CC BY-SA 4.0 许可协议
在这种情况下,
{}
调用值初始化。如果optional
的默认构造函数不是用户提供的(其中“非用户提供”的意思大致是“在类定义中隐式声明或显式默认”),则会导致整个对象的零初始化.是否这样做取决于该特定
std::optional
实现的实现细节。看起来 libstdc++ 的optional
的默认构造函数不是用户提供的,但 libc++ 是。