考虑这两种可以表示“可选int
”的方法:
using std_optional_int = std::optional<int>;
using my_optional_int = std::pair<int, bool>;
鉴于这两个功能...
auto get_std_optional_int() -> std_optional_int
{
return {42};
}
auto get_my_optional() -> my_optional_int
{
return {42, true};
}
...g++ trunk 和 clang++ trunk (带有 -std=c++17 -Ofast -fno-exceptions -fno- rtti
) 生成以下程序集:
get_std_optional_int():
mov rax, rdi
mov DWORD PTR [rdi], 42
mov BYTE PTR [rdi+4], 1
ret
get_my_optional():
movabs rax, 4294967338 // == 0x 0000 0001 0000 002a
ret
为什么get_std_optional_int()
需要三个mov
指令,而get_my_optional()
只需要一个movabs
? 这是 QoI 问题,还是 std::optional
的规范中的某些内容阻止了这种优化?
另外请注意,这些功能的用户可能会被完全优化出来:
volatile int a = 0;
volatile int b = 0;
int main()
{
a = get_std_optional_int().value();
b = get_my_optional().first;
}
...结果:
main:
mov DWORD PTR a[rip], 42
xor eax, eax
mov DWORD PTR b[rip], 42
ret
最佳答案
libstdc++ 显然没有实现 P0602 "variant and optional should propagate copy/move triviality" .您可以通过以下方式验证这一点:
static_assert(std::is_trivially_copyable_v<std::optional<int>>);
which fails for libstdc++, and passes for libc++ and the MSVC standard library (它确实需要一个合适的名称,因此我们不必将其称为“C++ 标准库的 MSVC 实现”或“MSVC STL”)。
当然,MSVC 仍然不会通过 optional<int>
因为 MS ABI 在寄存器中。
编辑:这个问题已在 GCC 8 发行系列中得到修复。
关于c++ - 为什么 std::optional<int> 的构造比 std::pair<int, bool> 更昂贵?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46544019/