Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
523 views
in Technique[技术] by (71.8m points)

c++ - Why is the construction of std::optional<int> more expensive than a std::pair<int, bool>?

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};
}

...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

live example on godbolt.org


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;
}

...results in:

main:
        mov     DWORD PTR a[rip], 42
        xor     eax, eax
        mov     DWORD PTR b[rip], 42
        ret
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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>>);

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").

Of course MSVC still won't pass an optional<int> in a register because the MS ABI.

EDIT: This issue has been fixed in the GCC 8 release series.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...