c++ - 为什么 std::optional<int> 的构造比 std::pair<int, bool> 更昂贵?

标签 c++ performance assembly x86-64 c++17

考虑这两种可以表示“可选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++ trunkclang++ 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

live example on godbolt.org


为什么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/

相关文章:

c++ - 维度结构重载

performance - 为什么Java IO中的默认缓冲区大小为8k?

java - 我应该避免使用静态变量吗

java - 多个(甚至可能未使用的)jar文件的大型类路径效率低下

c - 在汇编程序 AMD64 中,我调用 fprintf 但它一直无限循环

c++ - 简单的 g++ 内联汇编程序出错

c++ - std::unique_ptr 内存和性能

c++ - 如何在Linux/Mac上调用特定的EXE函数

c++ - Tic Tac Toe 游戏无法运行

assembly - 4.5 毫秒内可以处理多少个数组元素?