我认为初始化一个std::optional https://en.cppreference.com/w/cpp/utility/optional with std::nullopt https://en.cppreference.com/w/cpp/utility/optional/nullopt与默认构造相同。
它们被描述为相等的在 cppreference 处 https://en.cppreference.com/w/cpp/utility/optional/optional,如式(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 {};
}
编译器资源管理器似乎暗示 https://godbolt.org/z/mDeDZQ那个使用std::nullopt
将简单地设置one byte "has_value
" flag,
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(自 v11.1)和 Clang(因为 v12.0.1) 现在可以有效地处理这两种形式。 https://godbolt.org/z/5co5135rr