Skip to content

<vector>: vector's move ctor initializes members twice #1324

@StephanTLavavej

Description

@StephanTLavavej

@xiangfan-ms discovered that vector's move constructor zero-initializes its pointers before taking the other vector's pointers, and that this isn't optimized away in release mode. (Which results in larger, slower codegen, and probably inhibits further optimizations like memcpy coalescing.)

  1. vector's move constructor constructs its base before allocating the proxy and taking the other's pointers:

    STL/stl/inc/vector

    Lines 581 to 584 in 530bdc5

    vector(vector&& _Right) noexcept : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal())) {
    _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal()));
    _Move_construct(_Right, true_type{});
    }
  2. The base construction sets the pointers to null:
    _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {}
  3. Then _Move_construct calls _Take_contents which re-assigns the pointers:

    STL/stl/inc/vector

    Lines 556 to 558 in 530bdc5

    void _Move_construct(vector& _Right, true_type) noexcept { // move from _Right, stealing its contents
    _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2);
    }

    STL/stl/inc/vector

    Lines 384 to 393 in 530bdc5

    void _Take_contents(_Vector_val& _Right) noexcept {
    this->_Swap_proxy_and_iterators(_Right);
    _Myfirst = _Right._Myfirst;
    _Mylast = _Right._Mylast;
    _Myend = _Right._Myend;
    _Right._Myfirst = pointer();
    _Right._Mylast = pointer();
    _Right._Myend = pointer();
    }

I believe it's possible to change this behavior. We'd need to make _Vector_val constructible from three pointers, so we can directly initialize them. (This will work with _Compressed_pair's one-then-variadic-args - the one arg is for the allocator, the variadic args are sent to _Vector_val.) Then we'd need to allocate/swap proxies (which vanishes for release mode), and null out the other pointers. (This is noexcept so allocation failure is termination - no EH concerns. vNext will remove the allocation.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    fixedSomething works now, yay!performanceMust go faster

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions