问题描述
考虑以下两种可以表示可选int
"的方法:
Consider these two approaches that can represent an "optional int
":
using std_optional_int = std::optional<int>;
using my_optional_int = std::pair<int, bool>;
考虑到这两个功能...
Given these two functions...
auto get_std_optional_int() -> std_optional_int
{
return {42};
}
auto get_my_optional() -> my_optional_int
{
return {42, true};
}
... g ++主干和 clang ++主干 (带有-std=c++17 -Ofast -fno-exceptions -fno-rtti
)都会产生以下程序集:
...both g++ trunk and clang++ trunk (with -std=c++17 -Ofast -fno-exceptions -fno-rtti
) produce the following assembly:
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
的内容规范阻止了这种优化?
Why does get_std_optional_int()
require three mov
instructions, while get_my_optional()
only needs a single movabs
? Is this a QoI issue, or is there something in std::optional
's specification preventing this optimization?
还请注意,无论如何,这些功能的用户都可能被完全优化:
Also please note that users of the functions might be completely optimized out regardless:
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变量和可选变量应传播复制/移动琐碎" .您可以使用以下方法进行验证:
libstdc++ apparently does not implement P0602 "variant and optional should propagate copy/move triviality". You can verify this with:
static_assert(std::is_trivially_copyable_v<std::optional<int>>);
对于libstdc ++失败,而对于libc ++和MSVC标准库则通过(实际上需要适当的名称,因此我们不必将其称为"C ++标准库的MSVC实现"或"MSVC STL").
which fails for libstdc++, and passes for libc++ and the MSVC standard library (which really needs a proper name so we don't have to call it either "The MSVC implementation of the C++ standard library" or "The MSVC STL").
当然,由于MS ABI,MSVC still 不会在寄存器中传递optional<int>
.
Of course MSVC still won't pass an optional<int>
in a register because the MS ABI.
GCC 8版本系列中已解决此问题.
This issue has been fixed in the GCC 8 release series.
这篇关于为什么要构造std :: optional< int>比std :: pair< int,bool>更昂贵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!