std :: optional-用{}或std :: nullopt构造为空? [英] std::optional - construct empty with {} or std::nullopt?

查看:610
本文介绍了std :: optional-用{}或std :: nullopt构造为空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为用 std::optional https://en.cppreference.com/w/cpp/utility/optional/nullopt"rel =" noreferrer> std::nullopt 与默认构造相同.

I thought that initializing a std::optional with std::nullopt would be the same as default construction.

它们在cppreference中被描述为相同,形式为( 1)

但是,Clang和GCC似乎对玩具示例函数的处理方式有所不同.

However, both Clang and GCC seem to treat these toy example functions differently.

#include <optional>

struct Data {
    char large_data[0x10000];
};

std::optional<Data> nullopt_init() {
  return std::nullopt;
}

std::optional<Data> default_init() {
  return {};
}

编译器资源管理器似乎暗示使用std::nullopt只会设置包含"标志,

Compiler Explorer seems to imply that using std::nullopt will simply set the "contains" flag,

nullopt_init():
    mov     BYTE PTR [rdi+65536], 0
    mov     rax, rdi
    ret

虽然默认构造将值初始化整个类.这在功能上是等效的,但几乎总是昂贵的.

While default construction will value initialize the entire class. This is functionally equivalent, but almost always costlier.

default_init():
    sub     rsp, 8
    mov     edx, 65537
    xor     esi, esi
    call    memset
    add     rsp, 8
    ret

这是故意行为吗?什么时候应该优先使用一种形式?

推荐答案

对于gcc,使用默认初始化进行不必要的调零

For gcc, the unnecessary zeroing with default initialization

std::optional<Data> default_init() {
  std::optional<Data> o;
  return o;
}

错误86173 ,需要在编译器本身中进行修复.使用相同的libstdc ++,clang在此处不执行任何memset.

is bug 86173 and needs to be fixed in the compiler itself. Using the same libstdc++, clang does not perform any memset here.

现在,在您的代码中,您实际上是在对对象进行值初始化(通过列表初始化).看来std::optional的库实现有两个主要选项:或者使默认构造函数变得无关紧要(libstdc ++),这虽然具有一些优点,但是会强制整个缓冲区初始化为零.或者它们提供了仅初始化所需内容的默认构造函数(libc ++)(例如std::nullopt中的构造函数),但是它们却显得琐碎.可悲的是,似乎无法兼具两者的优势.我想我更喜欢第二个版本.同时,务实的是,使用std::nullopt中的构造函数而不会使代码复杂化似乎是个好主意.

Now in your code, you are actually value-initializing the object (through list-initialization). It appears that library implementations of std::optional have 2 main options: either they make the default constructor trivial (libstdc++), which has some advantages but forces zero-initialization of the whole buffer; or they provide a default constructor (libc++) that initializes only what is needed (like the constructor from std::nullopt), but they lose triviality. Sadly, it does not seem possible to have the advantages of both. I think I prefer the second version. In the mean time, pragmatically, using the constructor from std::nullopt where it does not complicate code seems to be a good idea.

这篇关于std :: optional-用{}或std :: nullopt构造为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆