Xiang Fan (@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.)
vector's move constructor constructs its base before allocating the proxy and taking the other's pointers:
|
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{});
|
|
}
|
- The base construction sets the pointers to null:
|
_Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {}
|
- Then
_Move_construct calls _Take_contents which re-assigns the pointers:
|
void _Move_construct(vector& _Right, true_type) noexcept { // move from _Right, stealing its contents
|
|
_Mypair._Myval2._Take_contents(_Right._Mypair._Myval2);
|
|
}
|
|
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.)
Xiang Fan (@xiangfan-ms) discovered that
vector's move constructor zero-initializes its pointers before taking the othervector's pointers, and that this isn't optimized away in release mode. (Which results in larger, slower codegen, and probably inhibits further optimizations likememcpycoalescing.)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
STL/stl/inc/vector
Line 375 in 530bdc5
_Move_constructcalls_Take_contentswhich re-assigns the pointers:STL/stl/inc/vector
Lines 556 to 558 in 530bdc5
STL/stl/inc/vector
Lines 384 to 393 in 530bdc5
I believe it's possible to change this behavior. We'd need to make
_Vector_valconstructible 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 isnoexceptso allocation failure is termination - no EH concerns. vNext will remove the allocation.)