std :: optional-用{}或std :: nullopt构造为空? [英] std::optional - construct empty with {} or 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屋!