本文介绍了为什么要构造std :: optional< int>比std :: pair< int,bool>更昂贵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下两种可以表示可选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

godbolt.org上的实时示例

为什么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&lt; int&gt;比std :: pair&lt; int,bool&gt;更昂贵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 15:40