考虑以下两种可以表示“可选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 ++干线和clang ++干线 (带有-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
optional
通过隐藏指针返回,这意味着类型定义包含禁止通过寄存器返回的内容。