std::optional - 用 {} 或 std::nullopt 构造空?

新手上路,请多包涵

我认为用 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 许可协议

阅读 596
1 个回答

在这种情况下, {} 调用值初始化。如果 optional 的默认构造函数不是用户提供的(其中“非用户提供”的意思大致是“在类定义中隐式声明或显式默认”),则会导致整个对象的零初始化.

是否这样做取决于该特定 std::optional 实现的实现细节。看起来 libstdc++ 的 optional 的默认构造函数不是用户提供的,但 libc++ 是。

原文由 T.C. 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题